2013-11-02 14 views
7

Supponiamo che io sono 3 colonne di una tabella - A, B e C. I vogliono assicurarsi che se inserisco un certo valore (ad esempio x) in una colonna A, non riesco a inserire una tupla che ha B o C uguale a x, cioè il valore x deve rimanere unico per la colonna A per tutte le tuple.SQL Oracle valore vincolo univoco tra più colonne

Nota che x può essere ripetuto in A per qualche altro tupla.

Sono consapevole della clausola UNIQUE in SQL, ma che è solo per garantire che un valore si verifica in una determinata colonna solo una volta. Poiché le istruzioni CHECK in Oracle non consentono le sottoquery, non riesco a capire come implementarlo.

EDIT (per aggiungere ulteriori informazioni)

chiave primaria è Employee_Number, mentre le 3 colonne in questione sono LandlineNo, MobileNo e VOIP. Così supponiamo che questo è stato una voce:

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

Poi questa voce per un altro tuple non sarebbe consentito -

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

D'altra parte, questo sarebbe bene (sì, 2 dipendenti possono avere la stesso numero dello stesso tipo)

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

Si può espandere la vostra domanda con un esempio di righe buoni e cattivi? Qual è la struttura e la chiave primaria del tavolo? –

+3

Sei bloccato con questo design del tavolo? Quello che stai chiedendo è che ogni numero garantisca di essere di un certo tipo. Quindi, perché non avere una tabella "numeri", la chiave primaria è il numero (o un ID più un vincolo univoco sui numeri se preferisci) e poi hai un tipo di colonna. Quindi ogni numero è unico e ha un solo tipo. Quindi nella tabella dei dipendenti hai solo tre chiavi esterne per quella tabella numerica (vale a dire tre numeri o tre ID). –

+0

quale versione di Oracle stai usando? – Sebas

risposta

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

Si può o non può funzionare a seconda della versione di 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

Problemi correlati