¿Cómo creo una restricción de tabla para evitar valores duplicados en dos columnas?

StackOverflow https://stackoverflow.com/questions/626609

  •  06-07-2019
  •  | 
  •  

Pregunta

Tengo la siguiente tabla:

CREATE TABLE [dbo].[EntityAttributeRelship](
    [IdNmb] [int] IDENTITY(1,1) NOT NULL,
    [EntityIdNmb] [int] NOT NULL,
    [AttributeIdNmb] [int] NOT NULL,
    [IsActive] [bit] NOT NULL CONSTRAINT [DF_EntityAttributeRelship_IsActive]  DEFAULT ((0)),
CONSTRAINT [PK_EntityAttributeRelship] PRIMARY KEY CLUSTERED 
([IdNmb] ASC) WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]) ON [PRIMARY]

Una parte de los datos en la tabla se parece a esto:

IdNmb    EntityIdNmb    AttributeIdNmb  IsActive
1        22             7               0
2        22             8               0
3        22             9               0
4        22             10              1

Quiero agregar una restricción para asegurarme de que nadie agregue o actualice un registro para tener IsActive = 1, si ya hay un registro para EntityIdNmb donde IsActive = 1.

¿Cómo hago esto?

¿Fue útil?

Solución

Si está utilizando SQLServer, puede crear una vista indexada agrupada.

CREATE VIEW dbo.VIEW_EntityAttributeRelship WITH SCHEMABINDING AS
SELECT EntityIdNmb 
FROM dbo.EntityAttributeRelship
WHERE IsActive = 1
GO

CREATE UNIQUE CLUSTERED INDEX UIX_VIEW_ENTITYATTRIBUTERELSHIP 
  ON dbo.VIEW_EntityAttributeRelship (EntityIdNmb)

Esto garantiza que solo haya un EntityIdNmb en su tabla con IsActive = 1.

Otros consejos

Parece que necesita implementar un activador (suponiendo que su producto db lo admita). Si solo desea una entrada activa y una inactiva, funcionará un índice único. De lo contrario, deberá escribir algún tipo de restricción personalizada o un desencadenador (probablemente 2: uno para inserciones, uno para actualizaciones) que se asegura de que no tenga 2 registros con la misma identificación donde ambos están activos.

Si está utilizando MSSQL (creo que así es como se ve su sintaxis), cree una vista que incluya solo las filas con IsActive = 1, luego coloque un índice único en EntityIdNmb en la vista.

En PostgreSQL, con el que he trabajado más recientemente, puede crear un índice parcial: http://www.postgresql.org/docs/8.3/interactive/ indexes-partial.html

Lo que tiene que escribir el desencadenante es decidir si desea rechazar el registro, cambiar el valor a 0 en lugar de uno o actualizar el registro antiguo a cero y dejar que este se pare como uno. Si está eliminando el registro con el valor de 1, ¿necesita cambiar otro registro para que sea el activo, cómo elegir cuál? Una vez que pueda definir qué desea hacer dentro del activador, podemos ayudarlo a diseñar mejor el proceso.

Hacemos los dos últimos pasos para convertir cualquier dirección en la principal dirección de correo de nuestra base de datos. Nuestra regla de negocio es una y solo una dirección puede ser la principal y si hay alguna dirección, debe marcarse como la principal. La clave para este tipo de desencadenante es recordar que las inserciones / actualizaciones / eliminaciones pueden ocurrir en lotes (incluso si esta no es la norma) y asegurarse de que el desencadenante funcione de manera basada en conjuntos. Cuando llegué, el nuestro implementó el procesamiento de varias filas a través de un cursor que se convirtió en algo malo cuando tuve que actualizar 200,000 direcciones en una importación. (Nota para los inexpertos: ¡nunca use un cursor en un disparador!)

¿Para qué se utilizarán los registros inactivos? ¿Están sin uso y simplemente están ahí para realizar un seguimiento de los registros activos anteriormente? Si es así, ¿sería posible dividir los datos en varias tablas? Algo así como ...

EntityAttributeRelship (IDNmb, EntityIDNmb, AttributeIDNmb)

EntityAttributeRelshipHistory (IDNmb, EntityIDNmb, AttributeIDNmb)

Si está en la tabla EntityAttributeRelship, está activo. Si está en la tabla de historial, entonces se activó en algún momento y, desde entonces, se ha desactivado.

Si necesita todo en una tabla, me gustaría seguir con la sugerencia de todd.run de usar un activador.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top