2013-11-02 9 views
7

Angenommen, ich habe 3 Spalten in einer Tabelle - A, B und C. Ich möchte sicherstellen, dass, wenn ich einen Wert (sagen x) in eine Spalte A einfügen, kann ich nicht einfügen ein Tupel, das entweder B oder C gleich x hat, dh der Wert x sollte für alle Tupel eindeutig für die Spalte A bleiben.SQL Oracle Constraint Wert eindeutig unter mehreren Spalten

Beachten Sie, dass x in A für ein anderes Tupel wiederholt werden kann.

Ich kenne die UNIQUE-Klausel in SQL, aber das ist nur um sicherzustellen, dass ein Wert in einer bestimmten Spalte nur einmal auftritt. Da CHECK-Anweisungen in Oracle keine Unterabfragen zulassen, kann ich nicht herausfinden, wie dies implementiert wird.

EDIT (mehr Info hinzufügen)

Primärschlüssel Employee_Number ist, während die 3 Spalten in Frage sind LandlineNo, MobileNo und VOIP. So nehme an, das ein Eintrag wurde:

Employee_Number = 1, LandlineNo = x, MobileNo = y, VOIP = z 

Dann ist dieser Eintrag für ein zweites Tupel würde nicht erlaubt sein -

Employee_Number = 2, LandlineNo = a, MobileNo = x, VOIP = c 

Auf der anderen Seite, dieser wäre gut (ja, 2 Angestellte kann die haben gleiche Anzahl der gleichen Art)

Employee_Number = 2, LandlineNo = x, MobileNo = b, VOIP = c 
+0

Können Sie Ihre Frage mit einem Beispiel für gute und schlechte Zeilen erweitern? Was ist die Struktur und der Primärschlüssel der Tabelle? –

+3

Sind Sie mit diesem Tischdesign festgefahren? Sie verlangen, dass jede Nummer von einem bestimmten Typ ist. Warum also nicht eine Tabelle "Zahlen" haben, primay Schlüssel ist die Zahl (oder eine ID plus eine eindeutige Beschränkung auf die Zahlen, wenn Sie das bevorzugen) und dann haben Sie einen Spaltentyp. Somit ist jede Nummer einzigartig und hat einen Typ. Dann haben Sie in Ihrer Angestelltentabelle nur drei Fremdschlüssel für diese Nummerentabelle (d. H. Drei Zahlen oder drei IDs). –

+0

welche Version von Oracle verwenden Sie? – Sebas

Antwort

2
CREATE MATERIALIZED VIEW mv_my 
BUILD IMMEDIATE 
REFRESH FAST ON COMMIT AS 
SELECT DISTINCT 
    CASE 
     WHEN t2.Employee_Number IS NOT NULL THEN 1 
     WHEN t3.Employee_Number IS NOT NULL THEN 1 
     WHEN t4.Employee_Number IS NOT NULL THEN 1 
     ELSE 0 
    END AS wrong 
FROM table t1 
    LEFT JOIN table t2 ON t2.MobileNo = t1.LandlineNo AND t2.Employee_Number != t1.Employee_Number 
    LEFT JOIN table t3 ON t3.VOIP = t1.LandlineNo AND t3.Employee_Number != t1.Employee_Number 
    LEFT JOIN table t4 ON t4.VOIP = t1.MobileNo AND t4.Employee_Number != t1.Employee_Number 
/

ALTER TABLE mv_my ADD CHECK(wrong = 0) 
/

Es kann oder auch nicht funktioniert auf Ihrer Oracle-Version abhängig (doc)

1
create table table1(
    a varchar2(20) not null, 
    b varchar2(20) not null, 
    c varchar2(20) not null 
) 
/
create table ctrs (
    val varchar2(20) unique, 
    ctr_a int, 
    ctr_b int, 
    ctr_c int, 
    check(ctr_a*ctr_b+ctr_a*ctr_c+ctr_b*ctr_c=0) 
) 
/
create trigger table1_trg 
before insert or update or delete on table1 
for each row 
begin 
    if deleting then 
     update ctrs set ctr_a = ctr_a - 1 where val = :old.a; 
     update ctrs set ctr_b = ctr_b - 1 where val = :old.b; 
     update ctrs set ctr_c = ctr_c - 1 where val = :old.c; 
    elsif inserting then 
     merge into ctrs using (
     select :new.a as x from dual union all 
     select :new.b as x from dual union all 
     select :new.c as x from dual 
    ) 
     on (val = x) 
     when not matched then 
     insert (val, ctr_a, ctr_b, ctr_c) values (x, 0, 0, 0); 
     update ctrs set ctr_a = ctr_a + 1 where val = :new.a; 
     update ctrs set ctr_b = ctr_b + 1 where val = :new.b; 
     update ctrs set ctr_c = ctr_c + 1 where val = :new.c; 
    else 
     update ctrs set ctr_a = ctr_a - 1 where val = :old.a; 
     update ctrs set ctr_b = ctr_b - 1 where val = :old.b; 
     update ctrs set ctr_c = ctr_c - 1 where val = :old.c; 
     merge into ctrs using (
     select :new.a as x from dual union all 
     select :new.b as x from dual union all 
     select :new.c as x from dual 
    ) 
     on (val = x) 
     when not matched then 
     insert (val, ctr_a, ctr_b, ctr_c) values (x, 0, 0, 0); 
     update ctrs set ctr_a = ctr_a + 1 where val = :new.a; 
     update ctrs set ctr_b = ctr_b + 1 where val = :new.b; 
     update ctrs set ctr_c = ctr_c + 1 where val = :new.c; 
    end if; 
end; 
/

fiddle

Verwandte Themen