MySQL:在两行之间交换 ID

Sah*_*rar 6 mysql update

我们有现有的表:


| id |    name    |   color   | calories |
------------------------------------------
| 1  | apple      | red       | 20       |
| 2  | orange     | orange    | 10       |
| 3  | grapes     | green     | 5        |
| 4  | bananas    | yellow    | 15       |
| 5  | plum       | purple    | 25       |
------------------------------------------
Run Code Online (Sandbox Code Playgroud)

id 是唯一的主键。我在编辑/更新记录时遇到了问题,当我注意更改例如第 3 行,id = 3id = 5第 5 行,id = 5id = 3...就像在第 3行和第 5行之间交换 id。当然有重复,但是如何解决这种情况...

但是 MySQL 从逻辑上抛出了错误。

SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '5' for key 'PRIMARY'
Run Code Online (Sandbox Code Playgroud)

我知道这是一个愚蠢的场景,但我们有一个客户想要这样。他想编辑/更新每个现有记录。

Phi*_* W. 17

列 id 是唯一的和主键......就像在第 3 行和第 5 行之间交换 id。

不应该这样做。

任何记录的主键应该创建/套/第一次创建记录和产生它应该永远不会改变,而不是对整个使用寿命该记录的,说得最多的点记录时最终被删除。

想象一下,如果银行对人们的银行账户进行重新编号,会造成怎样的混乱!

此外,虽然您在这里(还)似乎没有它们,但拥有主键的主要好处之一是其他表可以拥有引用它的外键。如果您开始更改主键值,那么您必须更改所有相应的外键值(数据库将强制执行此操作)。
我严重怀疑任何用户都会理解这一点。

... 客户 ... 想要编辑/更新每个现有记录。

无论如何允许他们编辑数据,而不是主键。
我将假设您为此提供了某种 UI,并且他们不会直接针对数据库发出 SQL。

如果他们试图将它用作某种序列或“订单”,那么使用单独的列可行的方法。主键,即使是自动递增的,也保证是唯一的保证它们是连续的或连续的。

  • “如果有人以/错误的顺序/...插入两行怎么办”:关系数据库表中的行*没有内在顺序*。主键不应该用于控制行的“排序”,因为它们/不/保证是连续的或连续的。如果您想要一个“序列”列,请创建您自己的列。 (8认同)

dan*_*ack 6

这些应该使用中间值包装在事务中;

begin;
set @from = 3;
set @to = 5;
set @tmpid = (2000000 + @from % 147483647);
update col set id=@tmpid where id = @from;
update col set id=@from where id=@to;
update col set id=@to where id = @tmpid;
commit;
Run Code Online (Sandbox Code Playgroud)

选择高端 @tmpid 命名空间以避免冲突很重要,以免以后遇到麻烦。