Når du har fjernet dine dubletter:
ALTER TABLE dbo.yourtablename
ADD CONSTRAINT uq_yourtablename UNIQUE(column1, column2);
eller
CREATE UNIQUE INDEX uq_yourtablename
ON dbo.yourtablename(column1, column2);
Selvfølgelig kan det ofte være bedre at tjekke for denne overtrædelse først, før du bare lader SQL Server forsøge at indsætte rækken og returnere en undtagelse (undtagelser er dyre).
-
Effektiviteten af forskellige fejlhåndteringsteknikker
-
Kontrollerer for potentielle overtrædelser af begrænsninger, før du går ind i TRY/CATCH
Hvis du vil forhindre undtagelser i at boble op til applikationen uden at foretage ændringer i applikationen, kan du bruge 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 hvis du ikke fortæller brugeren, at de ikke udførte indsættelsen, vil de undre sig over, hvorfor dataene ikke er der, og ingen undtagelse blev rapporteret.
REDIGER her er et eksempel, der gør præcis, hvad du beder om, endda ved at bruge de samme navne som dit spørgsmål, og beviser det. Du bør prøve det, før du antager, at ovenstående ideer kun behandler den ene eller den anden kolonne i modsætning til 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 alt dette:
ID Name Active PersonNumber
---- ------ ------ ------------
1 foo 1 22
2 foo 0 22
Fejlmeddelelse på sidste indsættelse:
Meddelelse 2627, niveau 14, tilstand 1, linje 3 Overtrædelse af UNIQUE KEY-begrænsning 'uq_Person'. Kan ikke indsætte dubletnøgle i objektet 'dbo.Person'. Udsagnet er blevet afsluttet.
Jeg bloggede også for nylig om en løsning til at anvende en unik begrænsning på to kolonner i begge rækkefølge :
- Håndhæv en unik begrænsning, hvor rækkefølgen ikke betyder noget