我有一个相当简单的表格,其中包含 ID
、Position
、Name
列。
ID Position Name
1 1 RecordX
2 3 RecordY
3 2 RecordZ
Position
列作为索引,用于按用户定义的顺序显示记录,它应该是唯一的,不能小于 1,也不能大于表中的记录数,在本例中为 3。该列不强制唯一性,因此暂时可以有 2 个具有相同 Position
的记录,但最终没有两个记录应该具有相同的位置以保证程序的正确运行。
目前,为了交换两条记录的位置,我需要进行 3 次查询,即:
找到其他记录的
ID
更新当前记录的
Position
以匹配其他记录的Position
通过之前找到的
ID
更新另一条记录的Position
(因为暂时会有两条记录具有相同的Position
,无法按Position
进行更新。
我觉得应该有一种方法可以减少对数据库的访问次数,从而减少 3 次查询。我应该如何处理这个问题?
最佳答案
单个“交换”操作...
交换(@old_pos,@new_pos)
UPDATE
my_table
SET
position = CASE WHEN position = @old_pos THEN @new_pos ELSE @old_pos END
WHERE
position IN (@old_pos, @new_pos)
不过,这并不容易扩展为交换操作表。这是因为它会尝试一次进行所有交换,而实际上交换必须以特定顺序发生......
此外,如果您想执行 SWAP(@id, @new_pos),您需要在要更新的表上执行子查询或自连接。 MySQL 不喜欢这样,尽管有一些方法可以解决这个限制,但它会让事情变得有点困惑......
UPDATE
my_table
INNER JOIN
(SELECT position AS old_pos, @new_pos AS new_pos FROM (SELECT position FROM my_table WHERE id = @id)) AS params
ON my_table.position IN (params.old_pos, params.new_pos)
SET
myTable.position = CASE WHEN position = old_pos THEN new_pos ELSE old_pos END
(我认为会起作用)
注意:
这两个假设都找到了@old_pos 和@new_pos,或者@id 和@new_pos,它不检查,如果它们不存在,将弄得一团糟。
这可以通过将其放入事务中来解决,如果 ROW_COUNT() 显示仅更新了 1 条记录,则回滚。
关于mysql - 将列值与另一条记录的同一列交换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8339414/