Restricción ÚNICA de SQL Server con NULOs duplicados [duplicar]


Posible Duplicado:
¿Cómo puedo crear una restricción única que también permite valores nulos en sql server

Tengo una tabla donde necesito forzar una columna para que tenga valores únicos. Esta columna debe ser nullable y por lógica de negocio múltiples valores NULL deben ser permitidos, mientras que otros valores duplicados no lo son.

La restricción ÚNICA de SQL Server no es buena en esta situación porque considera NULL como valores regulares, por lo que rechazará duplicados nulo.

Actualmente, la singularidad del valor es otorgada por el BLL, por lo que no estoy buscando un truco sucio para que funcione. Solo me gustaría saber si hay una solución limpia para hacer cumplir esta restricción en la base de datos.

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

Author: Community, 2009-11-25

6 answers

Si está utilizando SQL Server 2008 (no funcionará para la versión anterior) existe el concepto de un í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
 52
Author: LorenVS,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-06-01 11:03:26

Duplicado de esta pregunta?

El truco de la columna calculada es ampliamente conocido como un "nullbuster"; mis notas acreditan a 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)
)

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

ALTER DATABASE MyDatabase SET ARITHABORT ON
 4
Author: onedaywhen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 11:50:34

Si está utilizando SQL Server 2008, eche un vistazo a los índices filtrados para lograr lo que desea.

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

  1. Cree una columna calculada que use el valor de su columna "única" si no es NULL, de lo contrario utiliza el valor de la columna de clave Primaria de la fila (o cualquier columna que sea única).
  2. Aplique una restricción UNIQUE a la columna calculada.
 3
Author: Paul Turner,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-11-25 11:48:04
 2
Author: ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-11-25 11:50:40

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

Aquí está la fuente - Creando Vistas indexadas

 1
Author: Svetlozar Angelov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-11-25 11:46:25

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

 0
Author: pablox,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-11-25 11:50:40