Можно ли связать ограничение Unique с ограничением Check? - PullRequest
1 голос
/ 22 марта 2012

У меня есть таблица access, схема которой приведена ниже:

create table access (
    access_id int primary key identity,
    access_name varchar(50) not null,
    access_time datetime2 not null default (getdate()),
    access_type varchar(20) check (access_type in ('OUTER_PARTY','INNER_PARTY')),
    access_message varchar(100) not null,
)

Доступны только типы доступа OUTER_PARTY and INNER_PARTY.

Я пытаюсь добиться того, чтобы запись INNER_PARTY была только один раз в день для каждого логина (пользователя), но OUTER_PARTY можно записывать любое количество раз. Поэтому мне было интересно, возможно ли сделать это напрямую или есть идиома для создания такого рода ограничений.

Я проверил этот вопрос: Объединяя ограничения UNIQUE и CHECK , но не смог применить его к моей ситуации, так как стремился к другому.

Ответы [ 2 ]

6 голосов
/ 22 марта 2012

A отфильтрованный уникальный индекс может быть добавлен в таблицу. Этот индекс может быть основан на вычисляемом столбце, который удаляет компонент времени из столбца access_time.

create table access (
    access_id int primary key identity,
    access_name varchar(50) not null,
    access_time datetime2 not null default (SYSDATETIME()),
    access_type varchar(20) check (access_type in ('OUTER_PARTY','INNER_PARTY')),
    access_message varchar(100) not null,
    access_date as CAST(access_time as date)
)
go
create unique index IX_access_singleinnerperday on access (access_date,access_name) where access_type='INNER_PARTY'
go

Кажется, работает:

--these inserts are fine
insert into access (access_name,access_type,access_message)
select 'abc','inner_party','hello' union all
select 'def','outer_party','world'
go
--as are these
insert into access (access_name,access_type,access_message)
select 'abc','outer_party','hello' union all
select 'def','outer_party','world'
go
--but this one fails
insert into access (access_name,access_type,access_message)
select 'abc','inner_party','hello' union all
select 'def','inner_party','world'
go
2 голосов
/ 22 марта 2012

к сожалению, вы не можете добавить «если» в проверочное ограничение.Я советую использовать триггер:

create trigger myTrigger
on access
instead of insert
as
begin
  declare @access_name varchar(50)
  declare @access_type varchar(20)
  declare @access_time datetime2

  select @access_name = access_name, @access_type= access_type, @access_time=access_time from inserted

  if exists (select 1 from access where access_name=@access_name and access_type=@access_type and access_time=@access_time)  begin
    --raise excetion
  end else  begin
    --insert
  end
end 

вам придется отформатировать @access_time, чтобы учитывать только часть даты

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...