2009-06-21 5 views
2

J'ai une table de base de données Oracle sur laquelle je veux appliquer une contrainte unique. Le problème est que je veux seulement appliquer la contrainte si une colonne dans cette table est nulle,Contrainte Oracle unique avec clause where

ie. Si une ligne n'a pas de colonne deleted_date, appliquez la contrainte, sinon ignorez-la. Cela permettra de supprimer des enregistrements en douceur et d'ignorer les contraintes qui y sont associées.

Vous ne savez pas quoi faire?

Cheers, Mark

Répondre

6

Il suffit de créer une contrainte de plusieurs colonnes - la colonne que vous voulez être unique ainsi que la date de suppression. Toutes les lignes non supprimées auront une valeur unique et la date de suppression sera nulle. Toutes les lignes supprimées seront uniques en raison de la date de suppression (en supposant qu'il s'agit d'un horodatage et que la résolution est suffisante pour séparer toutes les suppressions). Si les lignes supprimées ne peuvent pas être séparées par la date de suppression, on pourrait penser à créer une nouvelle colonne et à l'ajouter à la contrainte pour unifier la date de suppression - mais ce serait une solution plutôt inélégante.

+0

homme, j'essayais de penser à celui-ci! Merci, cela fera très bien je pense – Mark

4

Si la résolution n'est pas suffisante, vous pouvez créer un index basé sur une fonction unique.

Un exemple:

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. 

Ceci est la solution décrite par Daniel. Si jamais il y a une possibilité que deux lignes sont supprimées au même moment (j'utilise uniquement la partie date ici), cette solution est assez bon:

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 

Dans ce cas, utiliser une fonction unique basée indice

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. 

Cordialement, Rob .

+0

+1: L'index basé sur la fonction unique est probablement mieux que la réponse actuellement acceptée –