在执行INSERT包含多行的语句时,我想跳过否则会导致失败的重复条目。经过一些研究,我的选择似乎是使用以下任一:
INSERT
ON DUPLICATE KEY UPDATE
INSERT IGNORE
我的这些假设是对的吗?简单地跳过可能导致重复的行并继续到其他行的最佳方法是什么?
我建议使用INSERT...ON DUPLICATE KEY UPDATE.
INSERT...ON DUPLICATE KEY UPDATE
如果使用INSERT IGNORE,则如果它导致重复键,则实际上不会插入该行。但该语句不会产生错误。它会生成一个警告。这些案例包括:
PRIMARY KEY
UNIQUE
NOT NULL
如果使用REPLACE,MySQL 实际上会在内部执行 aDELETE后跟 an INSERT,这会产生一些意想不到的副作用:
REPLACE
DELETE
更正: 两者都是 MySQL 特有REPLACE的INSERT...ON DUPLICATE KEY UPDATE非标准专有发明。ANSI SQL 2003 定义了一个MERGE可以解决相同需求(甚至更多)的语句,但 MySQL 不支持该MERGE语句。
MERGE
一位用户试图编辑这篇文章(编辑被版主拒绝)。该编辑尝试添加一个声明,该声明INSERT...ON DUPLICATE KEY UPDATE会导致分配一个新的自动增量 ID。确实 生成 了新的id ,但没有在更改的行中使用。
请参阅下面的演示,使用 Percona Server 5.5.28 进行测试。配置变量innodb_autoinc_lock_mode=1(默认):
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 foo\G 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 foo\G 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
上面演示了 IODKU 语句检测到重复,并调用更新来更改u. 请注意,AUTO_INCREMENT=3表示生成了一个 id,但未在该行中使用。
u
AUTO_INCREMENT=3
而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 | +----+------+