在不违反约束的情况下交换两个DB行

Cli*_*rce 5 sql t-sql sql-server atomic

我有一张桌子regionkey:

areaid  -- primary key, int
region  -- char(4)
locale  -- char(4)
Run Code Online (Sandbox Code Playgroud)

数据库的其余部分都是外键到areaid.在此表中,有一个具有唯一约束的(区域,区域设置)索引.

问题是我有两条记录:

101   MICH   DETR
102   ILLI   CHIC
Run Code Online (Sandbox Code Playgroud)

我需要在它们之间交换(区域,区域设置)字段,以便我最终得到:

101   ILLI   CHIC
102   MICH   DETR
Run Code Online (Sandbox Code Playgroud)

天真的方法不起作用,因为它违反了区域和​​区域设置的唯一索引:

update regionkey
     set region='ILLI', locale='CHIC' where areaid = 101; -- FAILS
update regionkey
     set region='MICH', locale='DETR' where areaid = 102;
Run Code Online (Sandbox Code Playgroud)

我怎样才能做到这一点?有一种原子方式来进行交换吗?建议?

gbn*_*gbn 8

您不能在SQL Server中推迟多个语句中的约束检查(除非您禁用),因此您必须避免冲突或在一个语句中执行此操作

update
    regionkey 
set
    region= CASE areaid WHEN 101 THEN 'ILLI' ELSE 'MICH' END, 
    locale= CASE areaid WHEN 101 THEN 'CHIC' ELSE 'DETR' END
where
    areaid IN (101, 102); 
Run Code Online (Sandbox Code Playgroud)

或者,更常规地(在这个交易中)

update regionkey 
     set region='AAAA', locale='BBBB' where areaid = 101;
update regionkey 
     set region='MICH', locale='DETR' where areaid = 102;
update regionkey 
     set region='ILLI', locale='CHIC' where areaid = 101;
Run Code Online (Sandbox Code Playgroud)

编辑:为什么不交换键而不是值?除非areaid有一些含义,否则它通常会达到理智的结果

update
    regionkey 
set
    areaid = 203 - areaid 
where
    areaid IN (101, 102); 
Run Code Online (Sandbox Code Playgroud)