tutorial descargar sql sql-server

descargar - tsql sql server



Agregar restricción única a la combinación de dos columnas (2)

Tengo una mesa y, de alguna manera, la misma persona entró a mi mesa de Person dos veces. En este momento, la clave principal es solo un autonumber, pero existen otros dos campos que deseo forzar a que sean únicos.

Por ejemplo, los campos son:

ID Name Active PersonNumber

Solo quiero 1 registro con un único PersonNumber y Active = 1.
(Entonces la combinación de los dos campos debe ser única)

Cuál es la mejor manera en una tabla existente en el servidor SQL Puedo hacerlo así si alguien más hace una inserción con el mismo valor que un valor existente, falla así que no tengo que preocuparme por esto en el código de mi aplicación.


Esto también se puede hacer en la GUI:

  1. Debajo de la tabla "Persona", haga clic con el botón secundario en Índices
  2. Haga clic / pase el índice nuevo
  3. Haga clic en Índice no agrupado ...

  1. Se dará un nombre de Índice predeterminado, pero es posible que desee cambiarlo.
  2. Marque casilla de verificación única
  3. Haga clic en el botón Agregar ...

  1. Verifique las columnas que quiere incluir

  1. Haga clic en Aceptar en cada ventana.

Una vez que haya eliminado su (s) duplicado (s):

ALTER TABLE dbo.yourtablename ADD CONSTRAINT uq_yourtablename UNIQUE(column1, column2);

o

CREATE UNIQUE INDEX uq_yourtablename ON dbo.yourtablename(column1, column2);

Por supuesto, a menudo puede ser mejor verificar primero esta infracción, antes de dejar que SQL Server intente insertar la fila y devolver una excepción (las excepciones son costosas).

http://www.sqlperformance.com/2012/08/t-sql-queries/error-handling

http://www.mssqltips.com/sqlservertip/2632/checking-for-potential-constraint-violations-before-entering-sql-server-try-and-catch-logic/

Si desea evitar que las excepciones burbujeen en la aplicación, sin realizar cambios en la aplicación, puede usar un desencadenador INSTEAD OF :

CREATE TRIGGER dbo.BlockDuplicatesYourTable ON dbo.YourTable INSTEAD OF INSERT AS BEGIN SET NOCOUNT ON; IF NOT EXISTS (SELECT 1 FROM inserted AS i INNER JOIN dbo.YourTable AS t ON i.column1 = t.column1 AND i.column2 = t.column2 ) BEGIN INSERT dbo.YourTable(column1, column2, ...) SELECT column1, column2, ... FROM inserted; END ELSE BEGIN PRINT ''Did nothing.''; END END GO

Pero si no le dice al usuario que no realizó la inserción, se preguntará por qué los datos no están allí y no se informó ninguna excepción.

EDITAR aquí es un ejemplo que hace exactamente lo que estás pidiendo, incluso usando los mismos nombres que tu pregunta, y lo demuestra. Debes probarlo antes de asumir que las ideas anteriores solo tratan una columna u otra en oposición a la combinación ...

USE tempdb; GO CREATE TABLE dbo.Person ( ID INT IDENTITY(1,1) PRIMARY KEY, Name NVARCHAR(32), Active BIT, PersonNumber INT ); GO ALTER TABLE dbo.Person ADD CONSTRAINT uq_Person UNIQUE(PersonNumber, Active); GO -- succeeds: INSERT dbo.Person(Name, Active, PersonNumber) VALUES(N''foo'', 1, 22); GO -- succeeds: INSERT dbo.Person(Name, Active, PersonNumber) VALUES(N''foo'', 0, 22); GO -- fails: INSERT dbo.Person(Name, Active, PersonNumber) VALUES(N''foo'', 1, 22); GO

Datos en la tabla después de todo esto:

ID Name Active PersonNumber ---- ------ ------ ------------ 1 foo 1 22 2 foo 0 22

Mensaje de error en la última inserción:

Msg 2627, nivel 14, estado 1, infracción de la línea 3 de la restricción UNIQUE KEY ''uq_Person''. No se puede insertar una clave duplicada en el objeto ''dbo.Person''. La instrucción se ha terminado.