我有一个包含两个字段的 SQL 表:id
和 order
。
CREATE TABLE IF NOT EXISTS article (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`order` INT(11) UNIQUE,
PRIMARY KEY (`id`)
);
在此表中我有一些项目:
+----+-------+
| id | order |
+----+-------+
| 1 | 0 |
| 2 | 1 |
| 3 | 2 |
| 4 | 3 |
| 5 | 4 |
| 6 | 5 |
| 7 | 6 |
| 8 | 7 |
| 9 | 8 |
| 10 | 9 |
+----+-------+
现在我想更改一项的订单位置:id 为 3 的元素(订单位置 2)将移动到位置 6。因此,位置 4 和 6 之间的元素(包括最后一个)
必须减少他们的 order
字段。
结果应该是这样的:
+----+-------+
| id | order |
+----+-------+
| 1 | 0 |
| 2 | 1 |
| 4 | 2 | ⌉
| 5 | 3 | |
| 6 | 4 | | Updated items
| 7 | 5 | |
| 3 | 6 | ⌋
| 8 | 7 |
| 9 | 8 |
| 10 | 9 |
+----+-------+
当然,第一个更新 - 使用 order
字段 6
更新 id 3
的项目 - 很简单:
UPDATE article
SET article.order = 6
WHERE id = 1;
然后我可以减少大于 2 且小于 euql 的位置之间的项目:
UPDATE article
SET article.order = article.order -1
WHERE
article.order > 2
AND
article.order <= 6
;
但是这里有一个问题:order
字段是UNIQUE
。因此,我必须首先将我想要移动的项目设置为 NULL:
UPDATE article
SET article.order = NULL
WHERE id = 3;
UPDATE article
SET article.order = article.order -1
WHERE
article.order > 2
AND
article.order <= 6
;
UPDATE article
SET article.order = 6
WHERE id = 3;
有没有办法避免设置这个NULL
?
这是一个 fiddle :https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=342d714e88e68d3c4c6e0ca1ec8efa6c
最佳答案
Is there a way to avoid setting this NULL?
不在 MySQL 中。 SQL 标准定义了解决此特定问题的可延迟约束功能。不幸的是,MySQL 没有实现 SQL 规范的这一部分。空值是您唯一的选择。
现在,当一个约束被标记为可推迟时(如在 PostgreSQL 或 Oracle 中),其验证可以推迟到每个 SQL 语句执行结束,甚至整个事务结束;也就是说,它的完整验证仅在提交
时发生,在所有更新完成并且所有值都将再次恢复正常之后。
如您所见,除非您可以选择迁移到 PostgreSQL 或 Oracle(极不可能),否则您将不得不使用 null。
关于MySQL:避免在更新之前必须在 UNIQUE 字段上设置 NULL 值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70636531/