【问题标题】:A better way to swap two primary key values and circumvent a ORA-00001: unique constraint violated?交换两个主键值并规避 ORA-00001:违反唯一约束的更好方法?
【发布时间】:2017-02-02 16:07:09
【问题描述】:

目标: 交换两条记录的主键而不遇到 ORA-00001:违反唯一约束。 “有效”的解决方案(下文详述)只是一个愚蠢的 hack。是否有将约束强制执行推迟到事务提交的功能/技术?
就动机而言 - 使用此数据的遗留应用程序存在设计缺陷并依赖于 ID 顺序和值- 请求如下交换PK值:

BEFORE: 
388    English
389    French

AFTER:
389    English
388    French

什么不起作用:

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

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

“有效”的黑客/解决方案

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;

表定义:

CREATE TABLE SPOKEN_LANGUAGES
(
  ID             NUMBER(10)                     NOT NULL,
  LANGUAGE_NAME  VARCHAR2(40 BYTE)              NOT NULL
)

PK/唯一索引:

   CREATE UNIQUE INDEX SL_PK ON SPOKEN_LANGUAGES    (ID)

【问题讨论】:

  • 简单地删除索引、执行更新然后重建索引怎么样?
  • @BobC 这绝对是一个建议——应用程序开发人员似乎不愿意采用这种策略。我还建议我们重构架构和/或应用程序以支持他们试图完成的任务;而不是试图按原样“修复它”。
  • 这是一次性修复,还是某种定期维护?如果它是一次性的,那么我认为删除和重建索引没有什么大问题。话虽如此,@a_hourse 还是想出了正确的答案。但正如你所说,依赖于该排序的应用程序可能会在以后遇到其他问题......

标签: sql oracle oracle11g


【解决方案1】:

您需要在一个语句中完成:

UPDATE SPOKEN_LANGUAGES
   SET id = case when id = 388 then 389 else 388 end
WHERE id in (388,389);

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-11-06
  • 1970-01-01
  • 2016-04-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-11
相关资源
最近更新 更多