MySQL 使用唯一约束更新 sort_order 字段会导致违反唯一约束

标签 mysql sorting duplicates constraints unique

我有这个表结构:

表 1:id、group_id、label、sort_order

Keys: PK: id, UNIQUE: group_id+sort_order, INDEX: group_id

示例数据:

id   group_id   label       sort_order
50   1          Field 1     1 
51   1          Field 2     2
52   1          Field 3     3

其中 (group_id, sort_order) 是唯一键。

要更新前端的记录排列,sort_order 字段用于 order by 子句。用户可以通过在前端拖动标签来更新订单,这会传递 id,例如:52, 51,50,然后将其视为新的订单/排序。

预期结果:

id   group_id   label       sort_order
50   1          Field 1     3 
51   1          Field 2     2
52   1          Field 3     1

该过程应使用新的 sort_order 值更新所有 3 条记录。示例更新查询:

UPDATE Table1 SET sort_order = 1 WHERE id = 52 AND group_id = 1

但是,由于 sort_order 是唯一键的一部分,它会抛出错误,因为 group_id,sort_order 键已经存在。

我做了一个 hackish 解决方法,我更新了排序顺序两次,例如:通过将其更新为更高的值,例如:sort_order = actual_order + 1000 然后使用实际值再次更新,例如: sort_order = actual_order

更好的方法是什么?我应该完全删除唯一 key 吗?

--

编辑

--

为了更好地了解问题,这是我的 PHP 代码:

示例 fieldIds:52,51,5050,51,5251,52,50。顺序决定了新的排序方式。

public function updateSort($projectId, $groupId, $subgroupId, array $fieldIds)
{
    // Other stuff
    // ...

    $statement = create_a_prepared_statement(); // ...

    // Updating sort_order directly would result to unique key violation
    // so change the sort_order into some negative numbers and re-sort with
    // the actual orders
    foreach ($fieldIds as $sortIndex => $fieldId) {
        $sort = $sortIndex - 1000;
        $statement->execute(array(
            'id' => $fieldId,
            'project_id' => $projectId,
            'group_id' => $groupId,
            'subgroup_id' => $subgroupId,
            ':0' => $sort,
        ));
    }

    // Now sort it correctly
    foreach ($fieldIds as $sortIndex => $fieldId) {
        $sort = $sortIndex + 1;
        $statement->execute(array(
            'id' => $fieldId,
            'project_id' => $projectId,
            'group_id' => $groupId,
            'subgroup_id' => $subgroupId,
            ':0' => $sort,
        ));
    }

    return true;
}

最佳答案

考虑到您在此声明中所写的内容:

I did a hackish workaround where ...

我会表演那句话的前半部分,

sort_order = actual_order + 1000

然后停止(意味着您完成了)。

您将永远不会在 100 年内遇到最大值溢出。如果您担心这一点,请让您的年度事件(通过创建事件)提醒您离关注还有多远,并在关注时将该组恢复到 1+。

但是您需要更新任何给定的组 2M 次才能溢出。

关于MySQL 使用唯一约束更新 sort_order 字段会导致违反唯一约束,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32686093/

相关文章:

mysql - 选择一行没有重复条目

Mysql 重复行(忽略 id + 时间戳)而不命名查询中的所有其他列?

mysql - 如何将mysql数据库中的python时间戳转换为SQL查询中的日期

php - 两个数组之间的差异(抑制和添加的行)

javascript - MapReduce 上的 Riak 排序

database - Postgresql - 使用特殊字符、数字和字母对字符字段进行排序

MySQL:限制列中的重复次数

MySQL查询时间太长

php - 无法访问 WordPress 登录并且也丢失了电子邮件详细信息

c++ - 当价格 float 时对订单簿进行排序