我有这个表结构:
表 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,50
或 50,51,52
或 51,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/