当前位置: 首页 > 面试题库 >

如何在不违反唯一约束的情况下在MySQL中交换两行的值?

宇文良骏
2023-03-14
问题内容

我有一个带有优先级列的“任务”表,该表具有唯一的约束。

我试图交换两行的优先级值,但我一直违反约束。我在类似情况下的某个地方看到了该语句,但MySQL却没有。

UPDATE tasks 
SET priority = 
CASE
    WHEN priority=2 THEN 3 
    WHEN priority=3 THEN 2 
END

WHERE priority IN (2,3);

这将导致错误:

Error Code: 1062. Duplicate entry '3' for key 'priority_UNIQUE'

是否可以在MySQL中完成此操作而不使用伪造的值和多个查询?

编辑:

这是表的结构:

CREATE TABLE `tasks` (
  `id` int(11) NOT NULL,
  `name` varchar(200) DEFAULT NULL,
  `priority` varchar(45) DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `priority_UNIQUE` (`priority`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8

问题答案:

是否可以在MySQL中完成此操作而不使用伪造的值和多个查询?

(我想不到的)。

问题是MySQL如何处理更新。MySQL(与UPDATE正确实施的其他DBMS不同)以破碎的方式处理更新。它会UNIQUE在每行更新后强制检查(和其他)约束,而不是在整个UPDATE语句完成后(应该这样做)进行检查。因此,(大多数)其他DBMS都没有这个问题。

对于某些更新(例如增加所有或某些ID id=id+1),可以通过使用-另一个非标准功能- ORDER BY更新中的an来解决。

对于从两行交换值,此技巧无济于事。您必须使用NULL或虚假值(该值不存在,但您的列中允许使用)和2或3条语句。

您也可以暂时删除唯一约束,但是我认为这并不是一个好主意。

因此,如果唯一列是有符号整数并且没有负值,则可以在事务中使用2条语句:

START TRANSACTION ;
    UPDATE tasks 
    SET priority = 
      CASE
        WHEN priority = 2 THEN -3 
        WHEN priority = 3 THEN -2 
      END 
    WHERE priority IN (2,3) ;

    UPDATE tasks 
    SET priority = - priority
    WHERE priority IN (-2,-3) ;
COMMIT ;


 类似资料:
  • 问题内容: 我有一张桌子: 数据库的其余整个部分都用外键键入areaid。在此表中,有一个具有唯一约束的(区域,区域设置)索引。 问题是我有两条记录: 我需要在它们之间交换(region,locale)字段,这样我才能得出: 天真的方法行不通,因为它违反了区域和​​语言环境的唯一索引: 我怎样才能做到这一点?是否有原子方式进行交换?有什么建议吗? 问题答案: 您不能在SQL Server中推迟对多

  • 我正试图插入数据库,但我在日志上看到了这样的消息: 我找到了这个查询以获取违反的密钥:

  • 当并发客户机试图将数据插入子表时,我们面临唯一的约束冲突问题。 假设我们有1以下的表格。用户user_id、first_name、last_name。2.项目project_idproject_name和project_description。 两者都有着多对多的关系。 当两个客户端试图创建一个新用户时。假设client1创建了user1(id=aa1),子记录项目(id=1)。Client2还创

  • 这是我的stacktrace: 学生表: 学生实体:学生标识默认为自动递增 postgres控制台(这些学生由sql脚本创建): 在此处输入图像描述 我也尝试过这样生成,但这没有帮助 我用postgreql它似乎我有问题与id Generator,谢谢你的想法和答案

  • 问题内容: 我定义了一个MySQL表: 我在这里阅读到MySQL不支持带条件的。对于每个 customerId, 我们只有一个 primaryImage = 1 。 那么我还能采取什么措施来强制执行此约束? 问题答案: 完美支持独特的约束。 但是,它不支持部分约束/索引,因此您需要使用而不是标记非主图像。 您可以将任意数量的值插入到每个客户中,但只能插入一个非空值。