MySQL:避免在更新之前必须在 UNIQUE 字段上设置 NULL 值

标签 mysql sql database

我有一个包含两个字段的 SQL 表:idorder

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/

相关文章:

SQL 查找相同的组

mysql - 数据表和查表同时级联删除

mysql - Scriptella:在 onerror 标签中获取错误代码和消息

java - Prepare 语句出现无效的列索引错误

mysql - 可怕的多重连接需要将结果限制为 144

.net - 无需使用多个 IFS 即可搜索我的网站

database - Oracle 默认顺序为 NULL LAST

mysql - 如何永久修复 : Job for mysql. 服务失败,因为控制进程退出并显示错误代码

mysql - MySQL 查询速度能否取决于表大小?

MySQL - 每3小时的数据平均值?