Sqlserver
 sql >> Baza danych >  >> RDS >> Sqlserver

Dodaj unikalne ograniczenie do kombinacji dwóch kolumn

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


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Korzyści z używania notacji porządkowej SQL?

  2. Jak mogę ogólnie posortować kolumnę „Numer wersji” za pomocą zapytania SQL Server?

  3. Pozycje ORDER BY muszą pojawić się na liście wyboru, jeśli określono opcję SELECT DISTINCT

  4. Jak określić wartość pola, której nie można przekonwertować na (dziesiętne, zmiennoprzecinkowe, int) w SQL Server?

  5. SQL Server POKAŻ TABELI odpowiednik