Po usunięciu duplikatów:
ALTER TABLE dbo.yourtablename
ADD CONSTRAINT uq_yourtablename UNIQUE(column1, column2);
lub
CREATE UNIQUE INDEX uq_yourtablename
ON dbo.yourtablename(column1, column2);
Oczywiście często lepiej najpierw sprawdzić to naruszenie, zanim pozwolisz SQL Serverowi na wstawienie wiersza i zwrócenie wyjątku (wyjątki są drogie).
-
Wpływ na wydajność różnych technik obsługi błędów
-
Sprawdzanie potencjalnych naruszeń ograniczeń przed wejściem TRY/CATCH
Jeśli chcesz zapobiec przepuszczaniu wyjątków do aplikacji bez wprowadzania zmian w aplikacji, możesz użyć INSTEAD OF
wyzwalacz:
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
Ale jeśli nie powiesz użytkownikowi, że nie wykonał wstawiania, będą się zastanawiać, dlaczego nie ma tam danych i nie zgłoszono żadnego wyjątku.
EDYTUJ Oto przykład, który robi dokładnie to, o co prosisz, nawet używając tych samych nazw, co twoje pytanie, i to udowadnia. Powinieneś to wypróbować, zanim założysz, że powyższe pomysły traktują tylko jedną lub drugą kolumnę, a nie kombinację...
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
Dane w tabeli po tym wszystkim:
ID Name Active PersonNumber
---- ------ ------ ------------
1 foo 1 22
2 foo 0 22
Komunikat o błędzie przy ostatniej wstawce:
Msg 2627, poziom 14, stan 1, wiersz 3 Naruszenie ograniczenia UNIQUE KEY „uq_Person”. Nie można wstawić zduplikowanego klucza w obiekcie „dbo.Person”. Wyrażenie zostało zakończone.
Ostatnio pisałem też na blogu o rozwiązaniu polegającym na zastosowaniu ograniczenia unikatowości do dwóch kolumn w dowolnej kolejności :
- Egzekwuj unikalne ograniczenie tam, gdzie porządek nie ma znaczenia