【发布时间】:2015-12-17 14:44:42
【问题描述】:
我有这个表结构:
表 1:id, group_id, label, sort_order
密钥: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 键已存在,因此会引发错误。
我做了一个骇人听闻的解决方法,我两次更新排序顺序,例如:通过将其更新为更高的值,例如:sort_order = actual_order + 1000,然后使用实际值再次更新,例如:sort_order = actual_order。
更好的方法是什么?我应该完全删除唯一键吗?
--
编辑
--
为了更好地了解问题,这是我的 PHP 代码:
示例字段 ID: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;
}
【问题讨论】:
-
有什么原因不能将 sort_order 移出 PK 并将实际的唯一 ID 放入其中吗?
-
您的 hack 是一种合理的方法。我通常使用负值,因此如果出现问题,它们会立即显现出来。另一种可能性是使用
NULL值。 -
@MutuYolbulan 。 . . OP声明该组合是唯一键,而不是主键。我猜
id是主键。 -
@MutuYolbulan group_id+sort_order 是除自动增量 ID 之外的附加唯一键。更新了问题以添加密钥详细信息。
-
如果您必须将分组和排序设为唯一,除非您在更新之前删除整个约束然后将其放回,否则您的 hack 将是唯一的方法,我不建议这样做.
标签: mysql sorting duplicates constraints unique