更换两个主键值并绕过ORA-00001的更好方法:违反了唯一约束?

Bri*_*ian 2 sql oracle oracle11g

目标: 交换两个记录的主键而不会遇到ORA-00001:违反了唯一约束."有效"的解决方案(下面再说)只是一个愚蠢的黑客.在提交事务之前是否存在推迟约束强制执行的功能/技术?
至于动机 - 使用此数据的遗留应用程序存在设计缺陷并依赖于ID顺序和值 - 请求是交换PK值,如下所示:

BEFORE: 
388    English
389    French

AFTER:
389    English
388    French
Run Code Online (Sandbox Code Playgroud)

什么不起作用:

BEGIN
   UPDATE SPOKEN_LANGUAGES
      SET id = 388
    WHERE id = 389;

   UPDATE SPOKEN_LANGUAGES
      SET id = 389
    WHERE id = 388;
END;
Run Code Online (Sandbox Code Playgroud)

黑客/解决方案"有效"

DECLARE
  V_MAGIC_NUMBER   NUMBER := 9999999;
BEGIN
  UPDATE SPOKEN_LANGUAGES
     SET id = 388 + V_MAGIC_NUMBER
   WHERE id = 389;

  UPDATE SPOKEN_LANGUAGES
     SET id = 389 + V_MAGIC_NUMBER
   WHERE id = 388;

  UPDATE SPOKEN_LANGUAGES
     SET id = id - V_MAGIC_NUMBER
   WHERE id = 389 + V_MAGIC_NUMBER;

  UPDATE SPOKEN_LANGUAGES
     SET id = id - V_MAGIC_NUMBER
   WHERE id = 388 + V_MAGIC_NUMBER;

END;
Run Code Online (Sandbox Code Playgroud)

表定义:

CREATE TABLE SPOKEN_LANGUAGES
(
  ID             NUMBER(10)                     NOT NULL,
  LANGUAGE_NAME  VARCHAR2(40 BYTE)              NOT NULL
)
Run Code Online (Sandbox Code Playgroud)

PK/UNIQUE INDEX:

   CREATE UNIQUE INDEX SL_PK ON SPOKEN_LANGUAGES    (ID)
Run Code Online (Sandbox Code Playgroud)

a_h*_*ame 7

您需要在一个语句中执行此操作:

UPDATE SPOKEN_LANGUAGES
   SET id = case when id = 388 then 389 else 388 end
WHERE id in (388,389);
Run Code Online (Sandbox Code Playgroud)