2009-11-25 34 views
30

Duplicar posibles:
How do I create unique constraint that also allows nulls in sql serverSQL Server restricción UNIQUE con nulos duplicados

Tengo una tabla donde tengo que forzar una columna de tener valores únicos. Esta columna debe ser nulable y, por lógica de negocio, se deben permitir múltiples valores NULL, mientras que otros valores duplicados no lo son.

SQL Server La restricción UNIQUE no es buena en esta situación porque considera NULL como valores normales, por lo que rechazará NULL duplicados.

Actualmente, la BLL otorga la exclusividad de los valores, así que no estoy buscando un truco sucio para que funcione. Simplemente me gustaría saber si hay una solución limpia para hacer cumplir esta restricción en el DB.

Y sí, sé que puedo escribir un disparador para hacer eso: ¿es la única solución un disparador? (¿o la mejor solución de todos modos?)

Respuesta

51

Si está utilizando SQL Server 2008 (no funcionará para versiones anteriores) existe el concepto de índice filtrado. Puede crear el índice en un subconjunto filtrado de la tabla.

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

Estamos usando SQL Server 2008, eso es todo, gracias. – Patonza

+0

Eso está funcionando. ¡Gracias! –

+0

¿Qué significa "Columnas" significa? – Tschallacka

1

Puede crear una vista en la que solo seleccione valores no nulos y cree un índice en ella.

Aquí es la fuente - Creating Indexed Views

3

Si está utilizando SQL Server 2008, echar un vistazo en índices filtrados para lograr lo que quiere.

Para la versión anterior de SQL Server, una posible alternativa a un disparador implica una columna calculada:

  1. Crear una columna calculada que utiliza el valor de su columna "única" si no es NULL, de lo contrario se utiliza el valor de la columna Clave principal de la fila (o cualquier columna que sea única).
  2. Aplicar una restricción UNIQUE a la columna calculada.
+0

Truco muy interesante el uso de una columna calculada. Podría haber un problema de colisión entre el PK y el valor real del campo, pero con algunos prefijos debería funcionar. – Patonza

0

Debe utilizar UNIQUEIDENTIFIER en esa columna, puede ser nulo, y también es único por definición. Espero que ayude.

+0

Tengo que aplicar la constrint a una columna varchar para que no pueda usar UNIQUEIDENTIFIER. – Patonza

4

¿Duplicado de this question?

El truco de columnas calculado es ampliamente conocido como "nullbuster"; mi crédito notas 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) 
) 

Obras en SQL Server 2000. Es posible que necesite ARITHABORT en, por ejemplo,

ALTER DATABASE MyDatabase SET ARITHABORT ON 
+0

Parece más o menos lo mismo, no fue capaz de encontrar esa pregunta antes de publicarla. De todos modos, aquí tenemos algunas buenas respuestas sobre TSQL2008 "índices filtrados" (que ni siquiera sabía que existían), así que supongo que valió la pena la duplicación :) – Patonza

+0

Eso puede conducir a valores no únicos, considere dónde 'dupNulls .pk = 1, X = null && dupNulls.pk = 2, X = 2' –

+0

@Rowland Shaw: los valores utilizados para la restricción dupNulls_uqX UNIQUE serán '(NULL, 1) && (2, 0)'. No veo ningún valor duplicado. – onedaywhen

Cuestiones relacionadas