我有一个在两列上有唯一索引的表,id_parent和sort_order是准确的
+----+-----------+------------+-------------+-------------+-------------+
| id | id_parent | sort_order | some_data | other_data | more_data |
+----+-----------+------------+-------------+-------------+-------------+
| 1 | 1 | 1 | lorem ipsum | lorem ipsum | lorem ipsum |
| 2 | 1 | 2 | lorem ipsum | lorem ipsum | lorem ipsum |
| 3 | 1 | 3 | lorem ipsum | lorem ipsum | lorem ipsum |
+----+-----------+------------+-------------+-------------+-------------+
现在我想一次性更新它们,它们的数据和sort_order。 sort_order将从1 - 2 - 3
更改为,例如2 - 3 - 1
。
但是当我开始运行更新语句时,唯一索引阻止了我,就像预期的那样,说我不能有两行id_parent = 1 and sort_order = 2
。
好吧,我现在可以设置它4,按正确的顺序更新其他行,然后设置这个。
但是,我必须运行一个额外的声明,并且很可能为我的脚本语言添加额外的逻辑以确定更新的正确顺序。
我也使用ORM,它变得更加不方便。
我现在的问题是,是否有一些方法可以让mysql暂时忽略这个索引?就像启动一个特殊的事务一样,只有在提交之前才会计算索引?
答案 0 :(得分:6)
据我所知,这是不可能的。
我唯一能看到这样的事情就是你可以在myisam表上禁用非唯一键。但不是在InnoDB而不是在唯一键上。
但是,为了节省一两个更新,不需要确切的数字1,2和3.你可以有4,5和6.对吗?您可以按顺序使用它,而不是其他任何内容,因此确切的数字并不重要。如果你聪明的话,它甚至可以为你节省更新。从你的例子
update table set sort_order = 4 where sort_order = 1 and id = 1 and id_parent = 1;
新的排序顺序是2,3,1。只需一次更新。
答案 1 :(得分:4)
'但是当我开始运行更新语句 ...'时 - 我明白了,您尝试使用多个UPDATE语句更新值,就像在循环中一样。是这样吗?如何一次更新它们?像这样,例如:
UPDATE atable
SET sort_order = CASE sort_order WHEN 3 THEN 1 ELSE sort_order + 1 END
WHERE id_parent = 1
AND sort_order BETWEEN 1 AND 3
单个语句是原子的,因此,在此更新结束时,sort_order
的值虽然已更改,但仍然是唯一的。
我无法在MySQL中测试这个,对不起,但它肯定适用于SQL Server,我相信这种行为符合标准。
答案 2 :(得分:1)
注意:有些评论提到以下答案并不总能抑制唯一约束,尤其是在InnoDB中。如果您可以改进此答案,请点击"编辑"并做出改进。
您只需在脚本开头添加此行:
SET UNIQUE_CHECKS=0;
将此与此结合使用是很常见的:
SET FOREIGN_KEY_CHECKS=0;
此处的文档中提到了UNIQUE_CHECKS
变量:
http://dev.mysql.com/doc/refman/5.0/en/converting-tables-to-innodb.html