“INSERT IGNORE” vs “INSERT … ON DUPLICATE KEY UPDATE”
在执行包含许多行的
-
ON DUPLICATE KEY UPDATE 意味着以某种代价进行不必要的更新,或者 -
INSERT IGNORE 意味着邀请其他类型的未经宣告失败。
我对这些假设是对的吗? 简单地跳过可能导致重复的行并继续执行其他行的最佳方法是什么?
我建议使用
如果使用
-
在具有
PRIMARY KEY 或UNIQUE 约束的列中插入重复键。 -
将NULL插入到具有
NOT NULL 约束的列中。 - 将行插入分区表,但插入的值不会映射到分区。
如果使用
- 分配新的自动增量ID。
-
可以删除具有外键的从属行(如果使用级联外键)或者阻止
Replace 。 -
不必要地执行触发
DELETE 的触发器。 - 副作用也传播到复制从属。
更正:
用户尝试编辑此帖子(编辑被主持人拒绝)。编辑尝试添加声明
请参阅下面的演示,使用Percona Server 5.5.28进行测试。配置变量
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | 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语句检测到重复,并调用更新来更改
而
1 2 3 4 5 6 7 8 9 10 11 12 13 |
如果你想看看这一切意味着什么,这里是一切的吹嘘:
1 2 3 4 5 6 |
主键基于此快速参考表的两列。主键需要唯一值。
让我们开始:
1 2 3 4 5 6 7 8 9 10 11 12 | INSERT INTO users_partners (uid,pid) VALUES (1,1); ...1 row(s) affected INSERT INTO users_partners (uid,pid) VALUES (1,1); ...Error Code : 1062 ...Duplicate entry '1-1' for key 'PRIMARY' INSERT IGNORE INTO users_partners (uid,pid) VALUES (1,1); ...0 row(s) affected INSERT INTO users_partners (uid,pid) VALUES (1,1) ON DUPLICATE KEY UPDATE uid=uid ...0 row(s) affected |
请注意,上面通过设置列等于自身来节省了太多额外的工作,实际上不需要更新
现在有一些多行测试:
1 2 3 4 5 6 |
在控制台中没有生成其他消息,现在它在表数据中有这4个值。除了(1,1)之外我删除了所有内容,所以我可以在同一个游戏区域进行测试
1 2 3 4 5 |
所以你有它。由于这一切都是在一张几乎没有数据且没有生产的新桌子上进行的,因此执行的时间是微观的,无关紧要的。任何拥有真实数据的人都非常欢迎您提供。
要添加的重要内容:使用INSERT IGNORE并确实存在密钥违规时,MySQL不会发出警告!
如果您尝试一次插入100条记录,如果有一条有故障,您将进入交互模式:
Query OK, 99 rows affected (0.04 sec)
Records: 100 Duplicates: 1 Warnings: 0
如你所见:没有警告!在官方的Mysql文档中甚至错误地描述了这种行为。
如果需要通知您的脚本,如果没有添加某些记录(由于密钥违规),您必须调用mysql_info()并解析它以获取"Duplicates"值。
我经常使用
我知道这是旧的,但我会添加这个注释,以防其他人(像我)到达此页面,同时试图找到有关INSERT..IGNORE的信息。
如上所述,如果使用INSERT..IGNORE,则执行INSERT语句时发生的错误将被视为警告。
未明确提及的一件事是INSERT..IGNORE将导致无效值在插入时将被调整为最接近的值(而如果未使用IGNORE关键字,则无效值将导致查询中止)。
ON DUPLICATE KEY UPDATE不是真正的标准。它和REPLACE一样标准。请参见SQL MERGE。
基本上这两个命令都是标准命令的替代语法版本。
这将插入或删除然后插入。我倾向于首先进行
INSERT IGNORE的潜在危险。
如果您尝试插入更长的VARCHAR值,则定义了列 - 将截断并插入值即使启用严格模式也是如此。
如果要在表中插入主键或唯一索引的冲突,它将更新冲突行而不是插入该行。
句法:
现在,这个insert语句可能看起来与前面看到的不同。此insert语句尝试将table1中的行与a和b的值分别插入到列column1和column2中。
让我们深入理解这个陈述:
例如:此处column1被定义为table1中的主键。
现在,如果在table1中,在column1中没有值为"a"的行。所以这个语句会在table1中插入一行。
现在,如果在table1中,在column2中有一行值为"a"。因此,此语句将使用"c"更新行的column2值,其中column1值为"a"。
因此,如果要插入新行,则在主键或唯一索引的冲突上更新该行。
阅读此链接的更多信息
如果在查询集的末尾使用带有