Mysql暂时压制唯一索引

时间:2011-12-07 05:32:35

标签: mysql sql indexing sql-update

我有一个在两列上有唯一索引的表,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暂时忽略这个索引?就像启动一个特殊的事务一样,只有在提交之前才会计算索引?

3 个答案:

答案 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