När du har tagit bort dina dubbletter:
ALTER TABLE dbo.yourtablename
ADD CONSTRAINT uq_yourtablename UNIQUE(column1, column2);
eller
CREATE UNIQUE INDEX uq_yourtablename
ON dbo.yourtablename(column1, column2);
Naturligtvis kan det ofta vara bättre att kolla efter denna överträdelse först, innan du bara låter SQL Server försöka infoga raden och returnera ett undantag (undantag är dyra).
-
Prestandapåverkan av olika felhanteringstekniker
-
Söker efter potentiella överträdelser av begränsningar innan du går in i TRY/CATCH
Om du vill förhindra att undantag bubblar upp till applikationen, utan att göra ändringar i applikationen, kan du använda en INSTEAD OF
trigger:
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
Men om du inte berättar för användaren att de inte utförde infogningen kommer de att undra varför data inte finns där och inget undantag rapporterades.
REDIGERA här är ett exempel som gör precis vad du efterfrågar, även med samma namn som din fråga, och bevisar det. Du bör prova det innan du antar att idéerna ovan bara behandlar den ena eller den andra kolumnen i motsats till kombinationen...
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
Data i tabellen efter allt detta:
ID Name Active PersonNumber
---- ------ ------ ------------
1 foo 1 22
2 foo 0 22
Felmeddelande på den senaste infogningen:
Medd. 2627, Nivå 14, Tillstånd 1, Rad 3 Brott mot UNIQUE KEY-begränsningen 'uq_Person'. Det går inte att infoga dubblettnyckel i objektet 'dbo.Person'. Uttrycket har avslutats.
Jag bloggade också mer nyligen om en lösning för att tillämpa en unik begränsning på två kolumner i valfri ordning :
- Tillämpa en unik begränsning där ordning inte spelar någon roll