2010-10-22 8 views
5

Tengo una tabla, algo así comorestricción UNIQUE controlado por una columna de bits

FieldsOnForms(
FieldID int (FK_Fields) 
FormID int (FK_Forms) 
isDeleted bit 
) 

El par (fieldID, FormID) debe ser único, pero sólo si no se elimina la fila (isDeleted = 0).

¿Es posible definir tal restricción en SQLServer 2008? (sin utilizar activadores)

P.S. La configuración (FieldID, FormID, isDeleted) para ser única agrega la posibilidad de marcar una fila como eliminada, pero me gustaría tener la posibilidad de establecer n filas (por FieldID, FormID) en isDeleted = 1, y tener solo una con isDeleted = 0

Respuesta

12

usted puede tener una única índice, utilizando el SQL Server 2008 filtered indexes función, o puede aplicar un índice UNIQUE en una vista (índice filtrado del hombre pobre, va en contra de las versiones anteriores), pero no se puede tener una restricción ÚNICA como la que ha descrito.

Un ejemplo del índice filtrado:

CREATE UNIQUE NONCLUSTERED INDEX IX_FieldsOnForms_NonDeletedUnique ON FieldsOnForms (FieldID,FormID) WHERE isDeleted=0 
+0

+1 mejor respuesta ... – gbn

+0

Aunque tengo un error, debido al campo de bit (la conversión de una columna al tipo de datos de una constante no es compatible con los índices filtrados), este parece ser el solución que estaba buscando. – jaraics

+0

@jaraics - Acabo de crear la tabla en su pregunta, y luego el índice en mi respuesta, y se creó sin error. Además, si encuentra incompatibilidades de tipo de datos, generalmente es mejor CASTAR (o CONVERTIR) la constante al tipo de columna, en lugar de hacerlo al revés. No estoy seguro si eso solucionaría su problema. –

1

No, único medio realmente único. Tendrá que mover sus registros eliminados a otra tabla o cambiar IsDeleted a algo que puede ser único en todos los registros eliminados (por ejemplo, una marca de tiempo). Cualquiera de las soluciones requerirá trabajo adicional en su aplicación, en un procedimiento almacenado o en un desencadenante.

2

Puede cambiar su columna IsDeleted a DeletedDate y convertirla en DATETIME con la hora exacta en que se borró lógicamente la fila. De forma alternativa, puede agregar una columna DeletedDate y luego crear una columna calculada IsDeleted en contra de eso para que aún tenga esa columna disponible si se está utilizando en el código. Por supuesto, usted pondría un índice único sobre DeletetedDate (además del FieldID y FormId) en lugar de la columna IsDeleted. Eso permitiría exactamente una columna NULL.

Albin publicó una solución similar a esta, pero luego la eliminó. No estoy seguro de por qué, pero si vuelve a publicarlo, entonces el suyo estaba aquí antes que el mío. :)

+0

Esto parece ser una buena alternativa para los servidores SQL anteriores. – jaraics

Cuestiones relacionadas