2009-11-25 10 views
30

Eventuali duplicati:
How do I create unique constraint that also allows nulls in sql serverSQL Server vincolo UNIQUE con i NULL duplicati

Ho una tabella in cui ho bisogno di forzare una colonna di avere valori univoci. Questa colonna deve essere nullable e per logica di business devono essere consentiti più valori NULL, mentre altri valori duplicati no.

SQL Server Il vincolo UNIQUE non è valido in questa situazione poiché considera NULL valori normali, pertanto rifiuterà NULL duplicati.

Attualmente, l'unicità del valore è garantita dalla BLL, quindi non sto cercando un trucco sporco per farlo funzionare. Vorrei solo sapere se esiste una soluzione pulita per applicare questo vincolo nel DB.

E sì, so che posso scrivere un trigger per farlo: è un trigger l'unica soluzione? (o comunque la soluzione migliore?)

risposta

51

Se si utilizza SQL Server 2008 (non funzionerà per la versione precedente), esiste il concetto di indice filtrato. È possibile creare l'indice su un sottoinsieme filtrato della tabella.

CREATE UNIQUE INDEX indexName ON tableName(columns) INCLUDE includeColumns 
WHERE columnName IS NOT NULL 
+0

Utilizziamo SQL Server 2008, quindi è tutto, grazie. – Patonza

+0

Funziona. Grazie! –

+0

Che cosa significano le colonne di inclusione/significato? – Tschallacka

1

È possibile creare una vista in cui selezionare solo valori nulli e creare un indice su di esso.

Qui è la fonte - Creating Indexed Views

3

Se stai usando SQL Server 2008, uno sguardo in indici filtrati per ottenere quello che vuoi.

Per la versione precedente di SQL Server, una possibile alternativa a un trigger comporta una colonna calcolata:

  1. Creare una colonna calcolata che utilizza il valore della colonna "unico" se non è NULL, altrimenti usa il valore della colonna Chiave primaria della riga (o qualsiasi colonna che sarà unica).
  2. Applicare un vincolo UNIQUE alla colonna calcolata.
+0

Trucco molto interessante l'uso di una colonna calcolata. Potrebbe esserci un problema di collisione tra il PK e il valore effettivo del campo, ma con qualche prefisso dovrebbe funzionare. – Patonza

0

Si dovrebbe usare UNIQUEIDENTIFIER in quella colonna, può essere NULL ed è anche unico per definizione. Spero che questo aiuti.

+0

Devo applicare il costritt a una colonna varchar, quindi non posso usare UNIQUEIDENTIFIER. – Patonza

4

Duplicato di this question?

Il trucco di colonna calcolato è ampiamente noto come "nullbuster"; Le mie note di credito Steve Kass:

CREATE TABLE dupNulls (
pk int identity(1,1) primary key, 
X int NULL, 
nullbuster as (case when X is null then pk else 0 end), 
CONSTRAINT dupNulls_uqX UNIQUE (X,nullbuster) 
) 

Opere su SQL Server 2000. Potrebbe essere necessario ARITHABORT su esempio

ALTER DATABASE MyDatabase SET ARITHABORT ON 
+0

Sembra quasi lo stesso, non è stato in grado di trovare quella domanda prima di postare. Ad ogni modo, qui abbiamo una bella risposta su TSQL2008 "indici filtrati" (che non sapevo nemmeno esistessero), quindi suppongo valga la pena la duplicazione :) – Patonza

+0

Questo può portare a valori non univoci - considera dove 'dupNulls .pk = 1, X = null && dupNulls.pk = 2, X = 2' –

+0

@Rowland Shaw: i valori utilizzati per il vincolo UNIQUE dupNulls_uqX saranno '(NULL, 1) && (2, 0)'. Non vedo alcun valore duplicato. – onedaywhen

Problemi correlati