Vincolo univoco Oracle con clausola where
-
06-07-2019 - |
Domanda
Ho una tabella di database Oracle su cui voglio applicare un vincolo univoco. Il problema è che voglio applicare il vincolo solo se una colonna in quella tabella è nulla,
es. se una riga non ha una colonna delete_date, applica il vincolo, altrimenti ignoralo. Ciò consentirà di eliminare softmente i record e ignorare i vincoli su di essi.
Qualche idea su come farlo?
Saluti, Mark
Soluzione
Crea semplicemente un vincolo multi colonna: la colonna che vuoi essere unica più la data di eliminazione. Tutte le righe non eliminate avranno un valore univoco e la data di eliminazione sarà nulla. Tutte le righe eliminate saranno uniche a causa della data di eliminazione (supponendo che sia un timestamp e la risoluzione sia abbastanza buona da separare tutte le eliminazioni). Se le righe eliminate non possono essere separate dalla data di eliminazione, si potrebbe pensare di creare una nuova colonna e di aggiungerla al vincolo per unificare la data di eliminazione, ma questa sarebbe una soluzione piuttosto inelegante.
Altri suggerimenti
E se la risoluzione non è abbastanza buona, puoi creare un indice univoco basato sulle funzioni.
Un esempio:
SQL> create table t (id,col,deleted_date)
2 as
3 select 1, 99, null from dual union all
4 select 2, 99, date '2009-06-22' from dual
5 /
Tabel is aangemaakt.
SQL> alter table t add constraint t_pk primary key (id)
2 /
Tabel is gewijzigd.
SQL> alter table t add constraint t_uk1 unique (col,deleted_date)
2 /
Tabel is gewijzigd.
Questa è la soluzione descritta da Daniel. Se c'è mai la possibilità che due righe vengano eliminate contemporaneamente (sto usando solo la parte della data qui), questa soluzione non è abbastanza buona:
SQL> insert into t values (3, 99, date '2009-06-22')
2 /
insert into t values (3, 99, date '2009-06-22')
*
FOUT in regel 1:
.ORA-00001: unique constraint (RWK.T_UK1) violated
In tal caso, utilizzare un indice univoco basato sulle funzioni:
SQL> alter table t drop constraint t_uk1
2 /
Tabel is gewijzigd.
SQL> create unique index i1 on t (nvl2(deleted_date,null,col))
2 /
Index is aangemaakt.
SQL> insert into t values (3, 99, date '2009-06-22')
2 /
1 rij is aangemaakt.
Saluti, Rob.