我有这样的table结构
在表中插入行时,我使用以下查询: INSERT INTO table_blah ( material_item, ... hidden ) VALUES ( data, ... data ) ON DUPLICATE KEY UPDATE id = id, material_item = data, ... hidden = data;
当我第一次插入数据而不触发 ON DUPLICATE KEY
id增量很好:
但是当 ON DUPLICATE KEY
触发器,然后我插入一个新行id看起来很奇怪:
我怎样才能保持 auto increment
,即使触发,也会正确递增 ON DUPLICATE KEY
?
6条答案
按热度按时间nimxete21#
我只是想补充一句,因为我正试图找到我问题的答案。我无法停止重复的警告,并发现这是因为我把它设置为tinyint只允许127个条目,改为small/med/bigint允许更多
u5i3ibmn2#
这个问题很老了,但我回答它可能对某些人有帮助,要解决自动递增的问题,请在插入/重复更新部分之前使用以下代码并一起执行它们:
在一个声明中,应该是这样的:
c90pui9n3#
INSERT INTO table_blah ( material_item, ... hidden ) VALUES ( data, ... data ) ON DUPLICATE KEY UPDATE material_item = data, ... hidden = data
是删除id=id,因为它会自动添加where primary key=primary key。。。yws3nbqq4#
此行为记录在案(括号中的段落):
如果指定了on duplicate key update,并且插入了一行,这将导致在唯一索引或主键中出现重复值,mysql将执行旧行的更新。例如,如果列a被声明为unique并包含值1,则以下两个语句具有类似的效果:
(对于一个innodb表,其中a是一个自动递增列,其效果是不同的。对于自动增量列,insert语句会增加自动增量值,但update不会。)
这里有一个简单的解释。mysql尝试先执行insert。这是id自动递增的时候。一旦增加,它就会保持不变。然后检测到重复并进行更新。但是这个值被忽略了。
你不应该依赖
auto_increment
没有空隙的。如果这是一个要求,那么更新和插入的开销就要大得多。基本上,您需要在整个表上设置一个锁,并对需要重新编号的所有内容重新编号,通常使用触发器。更好的解决方案是计算输出的增量值。cuxqih215#
我经常通过创建一个临时表来处理这个问题,在临时表中记录记录是否是新的,只对不是新的行进行更新,并对新行进行插入。下面是一个完整的示例:
这个
INSERT IGNORE INTO
方法更简单,但它忽略了任何错误,这不是我想要的。我同意mysql的这种奇怪行为,但这是我们必须处理的。qlfbtfca6#
我也有同样的沮丧,我有一个解决办法。
让我先谈谈“间接费用”。当我第一次编写db更新代码时,它执行了太多单独的查询,花费了5个小时。一旦我把“复制密钥更新”我得到了大约50秒。太神了!无论如何,我解决它的方法意味着我必须做2个查询,所以我不是1分钟,而是延长到2分钟,我认为这是一个公平的成本考虑。
首先,我对所有数据(更新和插入)执行了一个标准的sql查询,但我包含了“忽略”,所以这只是绕过更新,只插入新内容。”在mytablename(stuff,stuff2)值中插入ignore“-不包含更新时的重复键。这意味着所有的新记录都会被输入。这些新记录还不能打破自动增量。
接下来,我对该sql语句执行了“on duplicate key update”版本。这不会破坏任何id,因为所有记录都已存在。它唯一中断的是自动递增值,在添加新记录时使用该值。因此,解决方案是在添加任何新记录之前修补这个自动增量值。
要修补自动增量值,请在php中使用以下sql:“alter table mytablename auto\u increment=”($表计数+1);
请记住将$tablecount实际设置为表计数,然后添加1,这样就可以进行进一步的更新了。
这既便宜又脏,但我喜欢。确保不要同时使用其他函数等写入数据库,因为它可能会出错。我想有办法锁table吗?但我的案子不需要这个。