mysql - 将列值与另一条记录的同一列交换

标签 mysql sql

我有一个相当简单的表格,其中包含 IDPositionName 列。

ID  Position  Name
1   1         RecordX
2   3         RecordY
3   2         RecordZ

Position 列作为索引,用于按用户定义的顺序显示记录,它应该是唯一的,不能小于 1,也不能大于表中的记录数,在本例中为 3。该列不强制唯一性,因此暂时可以有 2 个具有相同 Position 的记录,但最终没有两个记录应该具有相同的位置以保证程序的正确运行。 目前,为了交换两条记录的位置,我需要进行 3 次查询,即:

  1. 找到其他记录的ID

  2. 更新当前记录的Position以匹配其他记录的Position

  3. 通过之前找到的 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/

相关文章:

mysql - 如何减少mysql中的这段代码来分离给定的字符串

mysql - select max() 返回错误的列

mysql - Lazarus,无法使数据库更新工作。如何预览正在提交的内容?

sql - exec sp_updatestats 的作用是什么?

PHP HTTP_User_Agent,将访问者重定向到移动页面,网站性能下降

mysql - 选择计数(日期)并使用零值设置空日期

mysql - 通过执行 native 操作系统的命令(如 curl)通过 MySQL 调用 HTTP GET 请求

sql - Sum on a left join SQL

mysql - Sql查询连接两个表以获得最终输出

mysql - 安装QMYSQL驱动