0

私は間違ったデータを持つテーブルを持っています。データを修正している間に新しい間違ったデータが挿入されないようにしたいと思います。起こる。 私は最初に重複してはならない列に対して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. 

は、私が説明してきた何をする方法はありますか、私は間違った挿入を防止しなければなりません私は問題の起源を探している間別の方法ですか?どんな助言も高く評価されます。

+1

テーブルをクリーンアップするまで一時的な回避策であれば、新しい重複を防ぐためにトリガーを使用してから、適切な制約を削除して追加することができます。 – OldProgrammer

+0

問題文はあまり意味がありません。 col1、col3、col4に一意索引を作成したいが、(1、...、NULL、NULL)を複写できるようにしたいとします。これは、UNIQUEが意味するものではなく、3つの列にあります。問題は「一意性に違反する古いデータ」ではありません。最初にテーブルを作成してから、この一意制約を追加して初めてテーブルを作成したとしても、その例のすべての行を正確に追加することはできません。既存のデータとは何が関係していますか? – mathguy

+0

@mathguy UNIQUEを3つのカラムに値がある場合にのみ適用したいと思います。これは一時的な回避策であり、OldProgrammerが指摘しているように、私は問題の原因を突き止めてきれいな解決策を見つけるのにこれが必要です。 – EAmez

答えて

0

ここに1つの方法があります。コミット時にリフレッシュされたマテリアライズド・ビューを作成します(状況が許せば高速リフレッシュが望ましく、この場合はそうすべきです)。 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)にユニーク制約を設定します。

+0

しかし、ビュー内の制約は、「間違った」データが挿入されるのを防ぐものではありません。 また、ソリューションを試しましたが、MyTabにはPKがないため、各レコードを一意にする列は時には空である必要がある列なので、機能しません。ええ、私はこれが奇妙なシナリオだと知っています...しかし、それは他の誰かがずっと以前に作った方法です:( – EAmez

+1

PKの欠如は本当に問題ですが、そうでなければ、MV **の制約は避けます"間違った"データが挿入されています。このようなシナリオでは非常に一般的な方法ですが、私はそれを発明しただけではありませんでした。 MVは新しい行を拒否し、トランザクション全体が無効になります。 – mathguy

関連する問題