INSERT ... ON DUPLICATE KEY UPDATE Syntax

如果表上有唯一值约束,为防止insert时唯一值约束列上发生唯一键冲突报错,可以采用insert into table ... on duplicate update ...来做处理

测试表结构,id和col1上都有唯一值约束

CREATE TABLE `t1` (
  `id` int(11) NOT NULL,
  `col1` int(11) DEFAULT NULL,
  `col2` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `udk_col1` (`col1`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8

13:18:56[test](;)> select * from t1;
+----+------+------+
| id | col1 | col2 |
+----+------+------+
| 1 | 2 | 3 |
| 2 | 3 | 4 |
+----+------+------+
2 rows in set (0.00 sec)

当新插入的和主键冲突时

insert into t1 values(2,4,4) on duplicate key update col2=col2+1;
13:49:54[test](;)> select * from t1;
+----+------+------+
| id | col1 | col2 |
+----+------+------+
|  1 |    2 |    3 |
|  2 |    3 |    5 |
+----+------+------+
2 rows in set (0.01 sec)

相当与执行了 

update t1 set col2=col2+1 where id=2;

当主键有自增属性时,只insert时如果检测到冲突,会自增1,但是上面的写法就不会进行自增操作;还有值得关注的是当执行update后面的语句后,影响行数会变为2

当多个主键发生冲突时,且涉及到的行数大于1时只会对其中一行进行update

    
#相当于
update t1 set col2=col2+1 where id=1 or col1=3;
13:57:51[test](;)> select * from t1;
+----+------+------+
| id | col1 | col2 |
+----+------+------+
|  1 |    2 |    4 |
|  2 |    3 |    5 |
+----+------+------+
2 rows in set (0.00 sec)

当在两个列上创建唯一值约束时

alter table t1 add col3 int;
alter table t1 add unique udk_col2_col3(col2,col3);
14:35:28[test](;)> select * from t1;
+----+------+------+------+
| id | col1 | col2 | col3 |
+----+------+------+------+
|  1 |    2 |    3 | NULL |
|  2 |    3 |    5 | NULL |
+----+------+------+------+
2 rows in set (0.00 sec)
14:35:48[test](;)> insert into t1(col2,col3) values(5,null);
Query OK, 1 row affected (0.10 sec)
14:36:54[test](;)> insert into t1(col2,col3) values(5,1);
Query OK, 1 row affected (0.11 sec)

14:37:04[test](;)> insert into t1(col2,col3) values(5,1);
ERROR 1062 (23000): Duplicate entry '5-1' for key 'udk_col2_col3'
14:37:07[test](;)> select * from t1;  
+----+------+------+------+
| id | col1 | col2 | col3 |
+----+------+------+------+
|  1 |    2 |    3 | NULL |
|  2 |    3 |    5 | NULL |
|  4 | NULL |    5 | NULL |
|  5 | NULL |    5 |    1 |
+----+------+------+------+
4 rows in set (0.00 sec)

14:38:22[test](;)> insert into t1(col2,col3) values(5,1) on duplicate key update col1=col2+col3;
Query OK, 2 rows affected (0.11 sec)

14:38:24[test](;)> select * from t1;
+----+------+------+------+
| id | col1 | col2 | col3 |
+----+------+------+------+
|  1 |    2 |    3 | NULL |
|  2 |    3 |    5 | NULL |
|  4 | NULL |    5 | NULL |
|  5 |    6 |    5 |    1 |
+----+------+------+------+
4 rows in set (0.00 sec)

对于上面的操作,对于col2=5,co3 is null时再插入相同的值依然可以成功,说明唯一索引对null值不做约束

原文地址:https://www.cnblogs.com/Bccd/p/7401861.html