ON DUPLICATE KEY添加行

时间:2017-08-09 20:39:29

标签: mysql insert duplicates unique

好的,我有下表:

CREATE TABLE `Tags` (
  `tag_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `tag` varchar(100) DEFAULT NULL,
  PRIMARY KEY (`tag_id`),
  UNIQUE KEY `tag` (`tag`),
  KEY `tag_id` (`tag_id`)
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8;
SET FOREIGN_KEY_CHECKS=1;

当我运行以下查询时,它似乎是在增加主键,即使它找到重复项(即使它没有添加重复项)。

INSERT INTO Tags (tag) VALUES ('book'),('cats'),('dogs') ON DUPLICATE KEY UPDATE tag = tag

你得到......

tag_id | tag
==============================
1      | book
2      | robots
3      | doodles
5      | cats
6      | dogs
==============================

如何防止这种情况?

2 个答案:

答案 0 :(得分:2)

你无法真正阻止这一点,你不应该担心它。自动增加的ID中的差距几乎不是问题。

发生的事情是MySQL正在尝试插入行。为了插入行,它必须构造它 - 因此自动递增的列会递增。当找到该行时,插入失败,但自动递增已经递增。

如果您想最小化问题,可以尝试在尝试插入之前找到重复项

INSERT INTO Tags (tag) 
    SELECT t.tag
    FROM (SELECT 'book' as tag UNION ALL
          SELECT 'cats' as tag UNION ALL
          SELECT 'dogs' as tag
         ) t
    WHERE NOT EXISTS (SELECT 1 FROM Tags t2 WHERE t2.tag = t.tag)
    ON DUPLICATE KEY UPDATE tag = VALUES(tag);

这不是100%修复 - 子查询可能有重复项,或者其他进程可以在运行时更新表。但是,它通常会避免在不应插入记录时插入记录。

答案 1 :(得分:1)

结帐innodb_autoinc_lock_mode。它目前设定的是什么?设置innodb_autoinc_lock_mode = 0可能会为您提供所需内容,但默认为1

除此之外,您的密钥tag_idtag_id)是多余的,因为这已经是您的主要密钥。