SQL Constraint проверяет уникальные значения

У меня есть таблица, и мне нужно ограничить введенные данные, я уже использую триггер, но мне было интересно, могу ли я сделать одну и ту же задачу с ограничением.

Поля:

Id
Date
Passport
...
Deleted

Ограничение должно допускать n записей, в то время как поле " Удалено" равно 1, но если поле " Удалено" равно 0, должно быть только одна строка с той же датой и паспортом.

Должен работать для следующих шагов:

  1. Добавление строки с Id = 1, Date = 2018-05-01, Passport = MPEUIE80, Deleted = 0
  2. Удаление строки с Id = 1, поэтому поле Deleted будет равно 1
  3. Добавление строки с Id = 2, Date = 2018-05-01, Passport = MPEUIE80, Deleted = 0
  4. Удаление строки с Id = 2, поэтому поле Deleted будет равно 1
  5. Добавление строки с Id = 3, Date = 2018-05-01, Passport = MPEUIE80, Deleted = 0
  6. Добавление строки с Id = 4, Date = 2018-05-01, Passport = MPEUIE80, Deleted = 0

До пятого шага все работает, но на последнем шаге должна произойти ошибка, потому что я не могу обрабатывать две строки с той же датой, одним и тем же паспортом и с Deleted= 0

Заранее спасибо.

Ответ 1

Вы можете использовать отфильтрованный уникальный индекс:

create table [t](
    [id] [int] NULL,
    [date] [datetime] NULL,
    [passport] [char](8) NULL,
    [deleted] [int] NULL
)

create unique index unq_t_date_passport on t(date, passport)
    where deleted = 0;

РЕДАКТИРОВАТЬ:

Если отфильтрованные индексы не работают над вашей версией SQL Server, вы можете проверить уровень совместимости. Он должен быть доступен, если для совместимости установлено значение 100 или выше. Вы можете проверить версию своего сервера и уровень совместимости, используя:

SELECT SERVERPROPERTY('ProductVersion');
SELECT name, compatibility_level FROM sys.databases;

Существует еще один метод, который будет работать в SQL Server 2005, предполагая, что идентификатор уникален и неотрицателен. Он использует вычисляемый столбец, чтобы сделать по существу то же самое, что и отфильтрованный индекс:

alter table t
    add column deleted_id (case when deleted = 0 then -1 else id end) persisted;

create unique index unq_t_passport_date_deleted_id on t(passport, date, deleted_id);