OceanBase数据库使用 INSERT 语句违反唯一约束冲突解决办法及两者差异分析

当在OceanBase数据库上创建带有唯一性约束的表,在向表中插入唯一性约束的冲突的数据时会提示因违反唯一性约束报错,OceanBase在其官网上提供了两种解决策略,但其官网并未详细说明两种策略的差异,于是早上对两种策略进行一些测试,对比下两者的差异。

>如在测试中哪有错误的地方,还望对此熟悉的大牛多多指正,不胜感激。

一、创建带有唯一性约束表

复制代码
[admin@obproxy-node ~]$ obclient -h 10.110.3.152 -uroot@sys#obcluster -pob@Passwd -P2883 -c -A oceanbase
Welcome to the OceanBase.  Commands end with ; or \g.
Your OceanBase connection id is 36
Server version: OceanBase_CE 4.0.0.0 (r100000282022112511-dd289d2407609a88b1fcdf2be9e7c384cb8e19d0) (Built Nov 25 2022 11:58:08)
 
Copyright (c) 2000, 2018, OceanBase and/or its affiliates. All rights reserved.
 
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
 
obclient [oceanbase]> use test;
Database changed
obclient [test]> create table customer(
    ->     id number not null primary key,
    ->     name varchar(10) not null,
    ->     salary number,
    ->     create_time datetime not null default current_timestamp
    ->  );
Query OK, 0 rows affected (0.132 sec)
 
obclient [test]> desc customer;
+-------------+---------------+------+-----+-------------------+-------+
| Field       | Type          | Null | Key | Default           | Extra |
+-------------+---------------+------+-----+-------------------+-------+
| id          | decimal(10,0) | NO   | PRI | NULL              |       |
| name        | varchar(10)   | NO   |     | NULL              |       |
| salary      | decimal(10,0) | YES  |     | NULL              |       |
| create_time | datetime      | NO   |     | CURRENT_TIMESTAMP |       |
+-------------+---------------+------+-----+-------------------+-------+
4 rows in set (0.011 sec)

二、插入重复主键数据

复制代码
-- 当表上有唯一性约束的时候,插入相同的记录,数据库会报错。提示因有主键冲突,数据未插入
obclient [test]> insert into customer(id, name, salary)  values (1,'zhangsan', 3000) ,(1,'lisi', 10003);
ERROR 1062 (23000): Duplicate entry '1' for key 'PRIMARY'
obclient [test]> select * from customer;
Empty set (0.004 sec)

三、解决办法

根据OceanBase官网资料,提供两种避免约束冲突的办法,分别是INSERT IGNORE INTO和INSERT INTO ON DUPLICATE KEY UPDATE 两种办法可进行避免。

  • 通过 INSERT IGNORE INTO 避免约束冲突,IGNORE 关键字可以忽略由于约束冲突导致的 INSERT 失败的影响。

  • 通过 INSERT INTO ON DUPLICATE KEY UPDATE 避免约束冲突,可以指定对重复主键或唯一键的后续处理
    说明

  • 指定 ON DUPLICATE KEY UPDATE:当要插入的主键或唯一键有重复时,会用配置值替换待插入的值。

  • 不指定 ON DUPLICATE KEY UPDATE:当要插入的主键或唯一键有重复时,插入报错

复制代码
obclient [test]> insert ignore into customer(id, name, salary)  values (1,'zhangsan', 3000) ,(1,'lisi', 10003);
Query OK, 1 row affected (0.011 sec)
 
obclient [test]> select * from customer;
+----+----------+--------+---------------------+
| id | name     | salary | create_time         |
+----+----------+--------+---------------------+
|  1 | zhangsan |   3000 | 2022-12-20 10:08:17 |
+----+----------+--------+---------------------+
1 row in set (0.003 sec)
 
obclient [test]> insert into customer(id, name, salary) values (3,'zhaowu', 10003),(3, 'wangliu', 10004) on duplicate key update name=values(name);
Query OK, 3 rows affected (0.011 sec)
Records: 2  Duplicates: 1  Warnings: 0
 
obclient [test]> select * from customer;
+----+----------+--------+---------------------+
| id | name     | salary | create_time         |
+----+----------+--------+---------------------+
|  1 | zhangsan |   3000 | 2022-12-20 10:08:17 |
|  3 | wangliu  |  10003 | 2022-12-20 10:08:59 |
+----+----------+--------+---------------------+
2 rows in set (0.014 sec)
 
obclient [test]> insert into customer(id, name, salary) values (5,'xiaoming', 10003),(6, 'xiaowang', 10004) on duplicate key update name=values(name);
Query OK, 2 rows affected (0.012 sec)
Records: 2  Duplicates: 0  Warnings: 0
 
obclient [test]> select * from customer;
+----+----------+--------+---------------------+
| id | name     | salary | create_time         |
+----+----------+--------+---------------------+
|  1 | zhangsan |   3000 | 2022-12-20 10:08:17 |
|  3 | wangliu  |  10003 | 2022-12-20 10:08:59 |
|  5 | xiaoming |  10003 | 2022-12-20 10:10:09 |
|  6 | xiaowang |  10004 | 2022-12-20 10:10:09 |
+----+----------+--------+---------------------+
4 rows in set (0.005 sec)
 
obclient [test]> insert into customer(id, name, salary) values (7,'huawei', 10003),(7, 'aiguo', 10004) on duplicate key update name=values(name);
Query OK, 3 rows affected (0.006 sec)
Records: 2  Duplicates: 1  Warnings: 0
 
obclient [test]> select * from customer;
+----+----------+--------+---------------------+
| id | name     | salary | create_time         |
+----+----------+--------+---------------------+
|  1 | zhangsan |   3000 | 2022-12-20 10:08:17 |
|  3 | wangliu  |  10003 | 2022-12-20 10:08:59 |
|  5 | xiaoming |  10003 | 2022-12-20 10:10:09 |
|  6 | xiaowang |  10004 | 2022-12-20 10:10:09 |
|  7 | aiguo    |  10003 | 2022-12-20 10:12:19 |
+----+----------+--------+---------------------+
5 rows in set (0.001 sec)
 
obclient [test]> insert into customer(id, name, salary) values (8,'xiaoA', 10003),(8, 'xiaoB', 10004),(8, 'xiaoC', 10005) on duplicate key update name=values(name);
Query OK, 5 rows affected (0.009 sec)
Records: 3  Duplicates: 2  Warnings: 0
 
obclient [test]> select * from customer;
+----+----------+--------+---------------------+
| id | name     | salary | create_time         |
+----+----------+--------+---------------------+
|  1 | zhangsan |   3000 | 2022-12-20 10:08:17 |
|  3 | wangliu  |  10003 | 2022-12-20 10:08:59 |
|  5 | xiaoming |  10003 | 2022-12-20 10:10:09 |
|  6 | xiaowang |  10004 | 2022-12-20 10:10:09 |
|  7 | aiguo    |  10003 | 2022-12-20 10:12:19 |
|  8 | xiaoC    |  10003 | 2022-12-20 10:35:46 |
+----+----------+--------+---------------------+
6 rows in set (0.002 sec)

复制

四、差异分析

通过反复测试,发现INSERT IGNORE INTO和INSERT INTO ON DUPLICATE KEY UPDATE在使用上也有个小小的差异,就是使用INSERT IGNORE INTO插入带有唯一性约束数据时,会插入第一条value后的语句, 而使用INSERT INTO ON DUPLICATE KEY UPDATE插入带有唯一性约束数据时会插入最后一条value的语句。

相关推荐
morris1312 小时前
【redis】redis实现分布式锁
数据库·redis·缓存·分布式锁
hycccccch2 小时前
Canal+RabbitMQ实现MySQL数据增量同步
java·数据库·后端·rabbitmq
这个懒人3 小时前
深入解析Translog机制:Elasticsearch的数据守护者
数据库·elasticsearch·nosql·translog
Yan-英杰3 小时前
【百日精通JAVA | SQL篇 | 第二篇】数据库操作
服务器·数据库·sql
NineData3 小时前
NineData云原生智能数据管理平台新功能发布|2025年3月版
数据库
百代繁华一朝都-绮罗生5 小时前
检查是否存在占用内存过大的SQL
数据库·sql
吾日三省吾码5 小时前
Python 脚本:自动化你的日常任务
数据库·python·自动化
CZIDC5 小时前
win11 系统环境下 新安装 WSL ubuntu + ssh + gnome 桌面环境
数据库·ubuntu·ssh
直裾5 小时前
Mapreduce的使用
大数据·数据库·mapreduce
纪元A梦5 小时前
Redis最佳实践——首页推荐与商品列表缓存详解
数据库·redis·缓存