Dopo aver rimosso i tuoi duplicati:
ALTER TABLE dbo.yourtablename
ADD CONSTRAINT uq_yourtablename UNIQUE(column1, column2);
o
CREATE UNIQUE INDEX uq_yourtablename
ON dbo.yourtablename(column1, column2);
Ovviamente, spesso può essere meglio controllare prima questa violazione, prima di lasciare che SQL Server tenti di inserire la riga e restituire un'eccezione (le eccezioni sono costose).
-
Impatto sulle prestazioni delle diverse tecniche di gestione degli errori
-
Verifica di potenziali violazioni dei vincoli prima di accedere a TRY/CATCH
Se vuoi evitare che le eccezioni si riversino nell'applicazione, senza apportare modifiche all'applicazione, puoi utilizzare un 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
Ma se non dici all'utente che non ha eseguito l'inserimento, si chiederà perché i dati non sono presenti e non è stata segnalata alcuna eccezione.
MODIFICA ecco un esempio che fa esattamente quello che stai chiedendo, anche usando gli stessi nomi della tua domanda, e lo dimostra. Dovresti provarlo prima di presumere che le idee di cui sopra trattino solo una colonna o l'altra invece della combinazione...
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
I dati nella tabella dopo tutto questo:
ID Name Active PersonNumber
---- ------ ------ ------------
1 foo 1 22
2 foo 0 22
Messaggio di errore sull'ultimo inserto:
Msg 2627, Livello 14, Stato 1, Riga 3 Violazione del vincolo CHIAVE UNICA 'uq_Person'. Impossibile inserire una chiave duplicata nell'oggetto 'dbo.Person'. L'istruzione è stata terminata.
Inoltre ho scritto sul blog più recentemente su una soluzione per applicare un vincolo univoco a due colonne in entrambi gli ordini :
- Applica un vincolo unico laddove l'ordine non conta