2011-01-10 13 views
8

I vincoli di supporto Oracle con espressioni simili?Vincolo univoco Oracle con espressione

Avviso Z = 'N'

ALTER TABLE A ADD CONSTRAINT U_A_KEY UNIQUE(X,Y,Z = 'N'); 

È questo Unique constraint possibile?

Esempio:

INSERT INTO A VALUES('X','Y','N'); --OK 
INSERT INTO A VALUES('X','Y','Y'); --OK 
INSERT INTO A VALUES('X','Y','Y'); --OK 
INSERT INTO A VALUES('X','Y','N'); --VOLIATION 
+0

Significa che si desidera avere al massimo un record con Z = 'N' per ogni combinazione x, y? –

+0

Sì, è corretto. – JamesC

risposta

18

Forse questo dà un'idea

drop table tq84_n; 

create table tq84_n (
    x number, 
    y number, 
    z varchar2(10) 
); 

create unique index tq84_n_x on tq84_n (
    case when z = 'N' then x || '-' || y 
     else null 
    end 
); 

tardi:

insert into tq84_n values (4,5, 'N'); 

insert into tq84_n values (9,6, 'Y'); 
insert into tq84_n values (9,6, 'Y'); 

insert into tq84_n values (4,5, 'Y'); 

insert into tq84_n values (4,5, 'N'); 

L'ultimo che getta:

ORA-00001: unique constraint (SPEZMDBA.TQ84_N_X) violated 
+0

Che soddisfa il caso d'uso, grazie per il suggerimento. – JamesC

+1

+1 per mostrare la violazione del vincolo. –

6

L'approccio più semplice in questo caso è generalmente di creare un indice basato funzione. Qualcosa di simile

CREATE UNIQUE INDEX u_a_key 
    ON a((CASE WHEN z = 'N' THEN x ELSE null END), 
      (CASE WHEN z = 'N' THEN y ELSE null END)); 

Se z non è 'N', entrambe le dichiarazioni CASE valutare NULL e Oracle non deve memorizzare i valori y x & nella struttura dell'indice (rendendo l'indice più piccolo). Se z è 'N', i valori x & y vengono entrambi memorizzati nell'indice e l'indice si comporta come qualsiasi altro indice composto.

0

Quello che faccio in quella situazione ricorrendo è quello di creare una colonna per esempio Z nel tuo caso, che ha:

  • un particolare valore (ad esempio il "N") nel caso ho bisogno di essere unico
  • Null in caso contrario, il che significa sconosciuto: due valori sconosciuti sono considerati non essere uguali tra loro.

Quindi è possibile creare il vincolo unico UNIQUE(X,Y,Z).

Aggiungi due righe con uguale X e Y e Z = "N" e riceverai un errore; aggiungi due righe con uguale X e Y entrambe con Z = null e non lo farai.

+0

La colonna Z può contenere un altro valore che deve superare il vincolo. Domanda aggiornata con SQL per chiarire, grazie. – JamesC