Sqlserver
 sql >> Datenbank >  >> RDS >> Sqlserver

Fügen Sie der Kombination von zwei Spalten eine eindeutige Einschränkung hinzu

Nachdem Sie Ihr(e) Duplikat(e) entfernt haben:

ALTER TABLE dbo.yourtablename
  ADD CONSTRAINT uq_yourtablename UNIQUE(column1, column2);

oder

CREATE UNIQUE INDEX uq_yourtablename
  ON dbo.yourtablename(column1, column2);

Natürlich kann es oft besser sein, zuerst nach dieser Verletzung zu suchen, bevor Sie SQL Server einfach versuchen lassen, die Zeile einzufügen und eine Ausnahme zurückzugeben (Ausnahmen sind teuer).

  • Auswirkung verschiedener Fehlerbehandlungstechniken auf die Leistung

  • Prüfung auf mögliche Beschränkungsverletzungen vor der Eingabe von TRY/CATCH

Wenn Sie verhindern möchten, dass Ausnahmen in die Anwendung sprudeln, ohne Änderungen an der Anwendung vorzunehmen, können Sie einen INSTEAD OF verwenden Auslöser:

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

Aber wenn Sie dem Benutzer nicht mitteilen, dass er die Einfügung nicht durchgeführt hat, werden sie sich fragen, warum die Daten nicht vorhanden sind und keine Ausnahme gemeldet wurde.

BEARBEITEN Hier ist ein Beispiel, das genau das tut, wonach Sie fragen, und sogar dieselben Namen wie Ihre Frage verwendet, und dies beweist. Sie sollten es ausprobieren, bevor Sie davon ausgehen, dass die obigen Ideen nur die eine oder andere Spalte behandeln, im Gegensatz zur Kombination ...

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

Daten in der Tabelle danach:

ID   Name   Active PersonNumber
---- ------ ------ ------------
1    foo    1      22
2    foo    0      22

Fehlermeldung beim letzten Einfügen:

Msg 2627, Level 14, State 1, Line 3Violation of UNIQUE KEY Constraint 'uq_Person'. Doppelter Schlüssel kann nicht in Objekt „dbo.Person“ eingefügt werden. Die Anweisung wurde beendet.

Außerdem habe ich kürzlich über eine Lösung zum Anwenden einer Eindeutigkeitsbeschränkung auf zwei Spalten in beliebiger Reihenfolge gebloggt :

  • Erzwingen Sie eine eindeutige Beschränkung, bei der die Reihenfolge keine Rolle spielt