Une fois que vous avez supprimé votre ou vos doublons :
ALTER TABLE dbo.yourtablename
ADD CONSTRAINT uq_yourtablename UNIQUE(column1, column2);
ou
CREATE UNIQUE INDEX uq_yourtablename
ON dbo.yourtablename(column1, column2);
Bien sûr, il peut souvent être préférable de vérifier d'abord cette violation, avant de laisser SQL Server essayer d'insérer la ligne et de renvoyer une exception (les exceptions coûtent cher).
-
Impact sur les performances des différentes techniques de gestion des erreurs
-
Vérification des violations potentielles des contraintes avant d'entrer TRY/CATCH
Si vous souhaitez empêcher les exceptions de remonter jusqu'à l'application, sans apporter de modifications à l'application, vous pouvez utiliser un INSTEAD OF
déclencheur :
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
Mais si vous ne dites pas à l'utilisateur qu'il n'a pas effectué l'insertion, il se demandera pourquoi les données ne sont pas là et aucune exception n'a été signalée.
MODIFIER voici un exemple qui fait exactement ce que vous demandez, même en utilisant les mêmes noms que votre question, et le prouve. Vous devriez l'essayer avant de supposer que les idées ci-dessus ne traitent qu'une colonne ou l'autre par opposition à la combinaison...
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
Données dans le tableau après tout cela :
ID Name Active PersonNumber
---- ------ ------ ------------
1 foo 1 22
2 foo 0 22
Message d'erreur lors de la dernière insertion :
Msg 2627, niveau 14, état 1, ligne 3Violation de la contrainte UNIQUE KEY 'uq_Person'. Impossible d'insérer une clé en double dans l'objet 'dbo.Person'. L'instruction a été terminée.
J'ai également blogué plus récemment sur une solution pour appliquer une contrainte unique à deux colonnes dans n'importe quel ordre :
- Appliquer une contrainte unique là où l'ordre n'a pas d'importance