Create Unique Constraint over function based index with existing duplicate values

时间:2017-06-12 16:57:40

标签: oracle duplicates unique-constraint check-constraints deferred-execution

I have a table with wrong data and I'd like to prevent new wrong data from beeing inserted while I fix data and find out what process or where is the sentence making this happen. I first made a UQ constraint over the columns that shouldn't be duplicated, but this gets me into another problem: I need to apply uniqueness only when all the columns have value, if there are nulls I need duplicate records over these columns. Something like this:

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

If I create a constraint like this:

ALTER TABLE MYTAB 
ADD CONSTRAINT U_CONSTRAINT UNIQUE (COL1, COL3, COL4)  NOVALIDATE; 

Last insert will crash.

I've tried with

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) ;

But the create crashes because table has duplicate data. I'll need to create this index without validating existing data, wich means index will be applied only to new records inserted.

I've tried also with:

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; 

But this gives me error:

ORA-14196: Specified index cannot be used to enforce the constraint.

Is there a way to do what I've explained, or should I prevent wrong inserts in another way while I look for the origin of the problem? Any advice will be appreciated also.

1 个答案:

答案 0 :(得分:0)

这是一种可能的方法。创建一个物化视图,提交时刷新(如果情况允许,最好快速刷新;在这种情况下,他们应该)。 MV就像

create materialized view mymv
refresh fast on commit
as
select col1, col3, col4
from   mytab
where  col1 is not null and col3 is not null and col4 is not null
;

然后在MV上添加一个唯一约束(col1,col3,col4)。