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的语句。

相关推荐
小猿姐34 分钟前
Ape-DTS:开源 DTS 工具,助力自建 MySQL、PostgreSQL 迁移上云
数据库·mysql·postgresql·开源
百香果果ccc38 分钟前
MySQL中的单行函数和聚合函数
数据库·mysql
摸摸陌陌38 分钟前
Redis快速入门
数据库·redis·缓存
Elastic 中国社区官方博客1 小时前
Elasticsearch Serverless 中的数据流自动分片
大数据·数据库·elasticsearch·搜索引擎·serverless·时序数据库
Minyy111 小时前
牛客网刷题SQL--高级查询
数据库·sql
秋意钟1 小时前
MySQL基本架构
数据库·mysql·架构
朱小勇本勇2 小时前
Qt实现控件拖曳
开发语言·数据库·qt
m0_748245922 小时前
mysql之如何获知版本
数据库·mysql
纯洁的小魔鬼2 小时前
redis 基础
数据库·redis·命令行
I love this bad girl2 小时前
防火墙旁挂部署+故障切换
服务器·网络·数据库