【发布时间】: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 还是想出了正确的答案。但正如你所说,依赖于该排序的应用程序可能会在以后遇到其他问题......