I would recommend using INSERT...ON DUPLICATE KEY UPDATE
.
(我建议使用INSERT...ON DUPLICATE KEY UPDATE
。)
If you use INSERT IGNORE
, then the row won't actually be inserted if it results in a duplicate key.
(如果使用INSERT IGNORE
,那么如果该行导致重复的键,则实际上不会插入该行。)
But the statement won't generate an error. (但是该语句不会产生错误。)
It generates a warning instead. (而是生成警告。)
These cases include: (这些情况包括:)
- Inserting a duplicate key in columns with
PRIMARY KEY
or UNIQUE
constraints. (在具有PRIMARY KEY
或UNIQUE
约束的列中插入重复键。)
- Inserting a NULL into a column with a
NOT NULL
constraint. (将NULL插入具有NOT NULL
约束的列中。)
- Inserting a row to a partitioned table, but the values you insert don't map to a partition.
(在分区表中插入一行,但是您插入的值不会映射到分区。)
If you use REPLACE
, MySQL actually does a DELETE
followed by an INSERT
internally, which has some unexpected side effects:
(如果使用REPLACE
,MySQL实际上会在内部进行DELETE
并随后INSERT
,这会有一些意外的副作用:)
correction: both REPLACE
and INSERT...ON DUPLICATE KEY UPDATE
are non-standard, proprietary inventions specific to MySQL.
(修正: REPLACE
和INSERT...ON DUPLICATE KEY UPDATE
都是针对MySQL的非标准专有技术。)
ANSI SQL 2003 defines a MERGE
statement that can solve the same need (and more), but MySQL does not support the MERGE
statement. (ANSI SQL 2003定义了一个MERGE
语句,该语句可以解决相同的需求(甚至更多),但是MySQL不支持MERGE
语句。)
A user tried to edit this post (the edit was rejected by moderators).
(一位用户尝试编辑此帖子(主持人拒绝了该编辑)。)
The edit tried to add a claim that INSERT...ON DUPLICATE KEY UPDATE
causes a new auto-increment id to be allocated. (该编辑尝试添加一个声明,即INSERT...ON DUPLICATE KEY UPDATE
中INSERT...ON DUPLICATE KEY UPDATE
会导致分配新的自动增量ID。)
It's true that the new id is generated , but it is not used in the changed row. (确实会生成新的id,但是更改后的行中不会使用它。)
See demonstration below, tested with Percona Server 5.5.28.
(请参见下面的演示,该演示已通过Percona Server 5.5.28测试。)
The configuration variable innodb_autoinc_lock_mode=1
(the default): (配置变量innodb_autoinc_lock_mode=1
(默认值):)
mysql> create table foo (id serial primary key, u int, unique key (u));
mysql> insert into foo (u) values (10);
mysql> select * from foo;
+----+------+
| id | u |
+----+------+
| 1 | 10 |
+----+------+
mysql> show create table fooG
CREATE TABLE `foo` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`u` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `u` (`u`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=latin1
mysql> insert into foo (u) values (10) on duplicate key update u = 20;
mysql> select * from foo;
+----+------+
| id | u |
+----+------+
| 1 | 20 |
+----+------+
mysql> show create table fooG
CREATE TABLE `foo` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`u` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `u` (`u`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=latin1
The above demonstrates that the IODKU statement detects the duplicate, and invokes the update to change the value of u
.
(上面的示例说明IODKU语句检测到重复项,并调用更新以更改u
的值。)
Note the AUTO_INCREMENT=3
indicates an id was generated, but not used in the row. (请注意, AUTO_INCREMENT=3
表示生成了一个ID,但未在行中使用。)
Whereas REPLACE
does delete the original row and inserts a new row, generating and storing a new auto-increment id:
(REPLACE
确实会删除原始行并插入新行,从而生成并存储新的自动增量ID:)
mysql> select * from foo;
+----+------+
| id | u |
+----+------+
| 1 | 20 |
+----+------+
mysql> replace into foo (u) values (20);
mysql> select * from foo;
+----+------+
| id | u |
+----+------+
| 3 | 20 |
+----+------+