2013-11-02 26 views
7

Załóżmy, że mam 3 kolumny w tabeli - A, B i C. Chcę się upewnić, że jeśli wstawię pewną wartość (np. X) do kolumny A, nie mogę wstawić krotkę, która ma B lub C równe x, tj. wartość x powinna pozostać unikalna dla kolumny A dla wszystkich krotek.Niepowodzenie SQL Oracle unikatowe wśród wielu kolumn

Należy zauważyć, że x można powtórzyć w A dla innej krotki.

Jestem świadomy klauzuli UNIQUE w SQL, ale to tylko w celu zapewnienia, że ​​wartość występuje w danej kolumnie tylko raz. Ponieważ instrukcje CHECK w Oracle nie zezwalają na podzapytanie, nie mogę wymyślić, jak to zaimplementować.

EDIT (aby dodać więcej informacji)

Klucz podstawowy jest Employee_Number, natomiast 3 kolumny w pytaniu są LandlineNo, MobileNo i VoIP. Zatem załóżmy, był to jeden wpis:

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

Wtedy ten wpis na kolejny krotki byłoby nie wolno -

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

Z drugiej strony, ten będzie w porządku (tak, 2 pracowników może mieć samą ilość tego samego rodzaju)

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

można rozszerzyć swoje pytanie na przykładzie dobrych i złych wierszy? Jaka jest struktura i klucz podstawowy tabeli? –

+3

Czy utknąłeś przy tym projekcie stołu? To, o co prosisz, to posiadanie każdego numeru gwarantowanego określonego rodzaju. Dlaczego więc nie mieć tabeli "liczby", kluczem pierwszorzędnym jest liczba (lub identyfikator plus unikalne ograniczenie na liczbach, jeśli wolisz), a następnie masz typ kolumny. Każda liczba jest niepowtarzalna i ma jeden typ. Następnie w tabeli pracowników masz tylko trzy obce klucze do tej tabeli numerów (tj. Trzy liczby lub trzy identyfikatory). –

+0

której wersji Oracle używasz? – Sebas

Odpowiedz

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

To może lub nie może działać w zależności od wersji Oracle (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