【问题标题】:On DUPLICATE KEY UPDATE with unique columns在具有唯一列的 DUPLICATE KEY UPDATE 上
【发布时间】:2020-03-27 08:05:48
【问题描述】:

拥有一个包含数据表的一些 UI 设置的表,通常如下:

| ID  |   name | alias |   pos  | def_pos | disp |
+-----+--------+-------+--------+---------+------+
|  1  |  name1 | bar   |   1    |    1    |   1  | 
|  2  |  name2 | foo   |   3    |    2    |   1  |
|  3  |  name3 | bar   |   2    |    3    |   1  |
|  4  |  name4 | baz   |   4    |    4    |   0  |
  • ID:主要
  • 名称:唯一

这里pos可以由用户通过在图形界面中拖动列来更新。

由于nameid 是唯一的,我一次更新多行 我在更改值时使用INSERTON DUPLICATE KEY UPDATE 而不是UPDATE。因此,例如,如果从上面的示例中交换第 2 行和第 3 行:

INSERT INTO
    ui_data_columns (id, name, pos)
VALUES
    (2, '', 2),
    (3, '', 3)
ON DUPLICATE KEY UPDATE
    pos = VALUES(pos)

根据:

到目前为止一切顺利:P


现在我的想法是为posdef_pos 添加唯一约束,并且一列不能有相同的位置。不可能在 UI 中将两个列值设置为相同,但最好有约束,因为它们唯一的并且......嗯,学习。

挑战就变成了,如果尝试使用KEY UPDATE,则在交换两个值时会遇到冲突。因此,当pos 存在时,我不能说pos = VALUES(pos) - 即使它在同一个语句中得到纠正(如果你明白我的意思的话)。假设它们通常按顺序插入

INSERT INTO ui_data_columns (id, name, pos)
VALUES (2, '', 2)
ON DUPLICATE KEY UPDATE pos = VALUES(pos)

# Error: pos = 2 exists

即使这个修复是:

INSERT INTO ui_data_columns (id, name, pos)
VALUES (3, '', 3)
ON DUPLICATE KEY UPDATE pos = VALUES(pos)

这要怎么做?


小想法:

  • 一些查询魔法?
  • 使用没有约束的临时表副本清除和填充?
  • 先删除有问题的记录再插入?
  • 在插入期间删除约束然后重新应用?
  • ...

【问题讨论】:

  • INSERT .. ODKU 仅逐个插入/更新记录,而重新排列需要同时更新两条记录(或使用一些中间存储)。我不明白你为什么在需要更新时使用 INSERT .. ODKU...
  • 作为一个技巧,您可以尝试使用三重更新 - 在 I..ODKU 中使用 VALUES (2, '', -1), (3, '', 3), (2, '', 2)...
  • @Akina:我按照stackoverflow.com/a/34866431使用INSERT

标签: mysql


【解决方案1】:

一个技巧 - 使用中间。 IE。执行 3 次更新,而不是 2 次。

create table test (id int primary key, pos int unique);
insert into test values (1,1),(2,3),(3,2),(4,4);
select * from test;
编号 |位置 -: | --: 1 | 1 3 | 2 2 | 3 4 | 4
insert into test values
(3,3), (2,2)
on duplicate key update pos = values(pos);
键“test.pos”的重复条目“3”
select * from test;
编号 |位置 -: | --: 1 | 1 3 | 2 2 | 3 4 | 4
insert into test values
(2,0), (3,3), (2,2)
on duplicate key update pos = values(pos);

select * from test;
编号 |位置 -: | --: 1 | 1 2 | 2 3 | 3 4 | 4

db小提琴here

【讨论】:

  • 甜蜜。认为我可以通过一些修改来使用这种方法。 Q(我会更新)可能不清楚可以更新多行,而不仅仅是两行,所以我想我可以通过首先将所有 pos 值设置为负数,然后设置为真实值来构建查询(当构建查询时脚本。)。只需将pos 更改为有符号(将其设置为无符号,因为 col pos 不能为负 IRL) - 但可能是比移除唯一约束更好的折衷方案。
  • @user3342816 无符号可以使用零作为中间值,如果零值不用作常规值,则不需要更改数据类型。
  • 是的,但如果更新多条记录,一次只能有一条记录为零。必须构建查询才能以正确的顺序进行插入。必须看看最终会变得多么复杂。 IIRC MySQL 在唯一字段上接受 NULL,但据我回忆,这是非标准的。
  • 容易做到:(1, -3), (2, -2), (4, -1), ... (1, 3), (2, 2), (4, 1), ... 比较。
  • @user3342816 但是您也可以使用非常大的值 - 从 MAXVALUE 到您的数据类型。
猜你喜欢
  • 1970-01-01
  • 2010-11-20
  • 2018-01-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-09-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多