Sqlserver
 sql >> база данни >  >> RDS >> Sqlserver

Добавете уникално ограничение към комбинация от две колони

След като премахнете своите дубликати:

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

или

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

Разбира се, често може да е по-добре първо да проверите за това нарушение, преди просто да оставите SQL Server да опита да вмъкне реда и да върне изключение (изключенията са скъпи).

  • Въздействие върху производителността на различни техники за обработка на грешки

  • Проверка за потенциални нарушения на ограниченията, преди да влезете в TRY/CATCH

Ако искате да предотвратите появата на изключения в приложението, без да правите промени в приложението, можете да използвате INSTEAD OF задействане:

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

Но ако не кажете на потребителя, че не е извършил вмъкването, той ще се чуди защо данните не са там и не е докладвано изключение.

РЕДАКТИРАНЕ ето пример, който прави точно това, което искате, дори използва същите имена като вашия въпрос, и го доказва. Трябва да го изпробвате, преди да приемете, че горните идеи третират само една или друга колона, за разлика от комбинацията...

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

Данни в таблицата след всичко това:

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

Съобщение за грешка при последното вмъкване:

Съобщение 2627, ниво 14, състояние 1, ред 3 Нарушение на ограничението UNIQUE KEY 'uq_Person'. Не може да се вмъкне дублиран ключ в обект 'dbo.Person'. Изявлението е прекратено.

Също така наскоро писах в блог за решение за прилагане на уникално ограничение към две колони в всеки ред :

  • Прилагане на уникално ограничение, където редът няма значение


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Какво е LEN() в SQL Server?

  2. Как да пиша с помощта на BCP към отдалечен SQL сървър?

  3. В Sql Server как да завъртите за няколко колони

  4. Ефективни замествания на ISNUMERIC() на SQL Server?

  5. Как мога да търся всички колони в таблица?