【发布时间】:2017-06-12 16:57:40
【问题描述】:
我有一个包含错误数据的表,我想防止在我修复数据时插入新的错误数据并找出导致这种情况发生的过程或句子的位置。 我首先对不应该重复的列进行了 UQ 约束,但这让我遇到了另一个问题:只有当所有列都有值时,我才需要应用唯一性,如果有空值,我需要这些列上的重复记录。像这样的:
CREATE TABLE MYTAB (COL1 NUMBER, COL2 NUMBER, COL3 NUMBER, COL4 NUMBER); --EXAMPLE TABLE. I NEED NO DUPS OVER (COL1, COL3, COL4)
INSERT INTO MYTAB VALUES (1, 1, 1, 1); --OK
INSERT INTO MYTAB VALUES (1, 2, 1, 1); -- NOOK
INSERT INTO MYTAB VALUES (1, 3, NULL, NULL); --OK
INSERT INTO MYTAB VALUES (1, 4, NULL, NULL); --OK
如果我创建这样的约束:
ALTER TABLE MYTAB
ADD CONSTRAINT U_CONSTRAINT UNIQUE (COL1, COL3, COL4) NOVALIDATE;
最后一次插入会崩溃。
我试过了
CREATE UNIQUE INDEX FN_UIX_MYTAB
ON MYTAB (CASE WHEN COL2 IS NOT NULL THEN COL1 ELSE null END,
CASE WHEN COL2 IS NOT NULL THEN COL3 ELSE null END
CASE WHEN COL2 IS NOT NULL THEN COL4 ELSE null END) ;
但是由于表中有重复数据,创建崩溃。我需要在不验证现有数据的情况下创建此索引,这意味着索引将仅应用于插入的新记录。
我也尝试过:
CREATE INDEX FN_IX_MYTAB
ON MYTAB (CASE WHEN COL2 IS NOT NULL THEN COL1 ELSE null END,
CASE WHEN COL2 IS NOT NULL THEN COL3 ELSE null END,
CASE WHEN COL2 IS NOT NULL THEN COL4 ELSE null END) ;
ALTER TABLE MYTAB
ADD CONSTRAINT FN_UIX_MYTAB UNIQUE (COL1, COL3, COL4) USING INDEX FN_IX_MYTAB NOVALIDATE;
但这给了我错误:
ORA-14196: Specified index cannot be used to enforce the constraint.
有没有办法按照我的解释进行操作,或者我应该在寻找问题根源时以其他方式防止错误插入?任何建议也将不胜感激。
【问题讨论】:
-
如果在清理表之前这是一个临时解决方法,也许可以使用触发器来防止新的重复,然后删除并添加适当的约束。
-
您的问题陈述不太合理。您想在 col1、col3、col4 上创建唯一索引,但您希望允许 (1, ..., NULL, NULL) 被复制。这不是 UNIQUE 的意思,在这三列上 - 问题不是“违反唯一性的旧数据”。即使您首先创建表,然后添加此唯一约束,然后第一次填充表,您将无法添加示例中的所有行,正是由于这个原因。这与预先存在的数据有什么关系?
-
@mathguy 我希望只有当这 3 列具有价值时才应用 UNIQUE。这是一个临时解决方法,正如 OldProgrammer 所指出的那样,我只在找到问题的根源并找到干净的解决方案时才需要它。
标签: oracle duplicates unique-constraint check-constraints deferred-execution