Используйте Check Constraints, чтобы определить, является ли битовый столбец и установлен ли в true на основе другого значения столбца, возможно? - PullRequest
0 голосов
/ 13 января 2011

Для разработки,

возможно ли применить правило, в котором ТОЛЬКО одна запись может иметь столбец с именем IsPrimaryUser, установленный в true, тогда как для всех остальных, сгруппированных по другому столбцу, установлено значение false Условием для определения, какая запись будет иметь истинное поле IsPrimaryUser, будет столбец CompanyId.

Меня интересует только то, можно ли это сделать с помощью проверочных ограничений. Очевидно, что SQL-подход к чему-то подобному.

Пример:

Таблица пользователей

int UserId | int CompanyId | бит IsPrimaryUser

Данные:

UserId  |  CompanyId  | IsPrimaryUser
   1          1              1
   2          1              0
   3          1              0
   4          1              0
   5          2              1
   6          2              0
   7          2              0
   8          2              0

1 Ответ

3 голосов
/ 13 января 2011

Проверка Ограничения работают только в одной строке, но вы можете использовать скалярные UDF в пределах ограничения.

Вы можете нарушить однострочную проверку, используя UDF, которые проверяют другие строки в таблице.Хотя в отличие от триггера, в котором вы можете получить доступ к виртуальной таблице DELETED и обрабатывать ее по отдельности, SQL Server, похоже, хранит записи в виде транзакции и выполняет CHECK для каждой строки после изменения, а затем, наконец, принимает или прерывает CRUD в пакете.

См. Этот контрольный пример

Создать таблицу

create table usertable (UserId int,
CompanyId int, IsPrimaryUser int)

Заполнить

insert usertable select
1, 1, 1 union all select
2, 1, 0 union all select
3, 1, 0 union all select
4, 1, 0 union all select
5, 2, 1 union all select
6, 2, 0 union all select
7, 2, 0 union all select
8, 2, 0

Помощник скалярной функции

create function dbo.anyprimaryuser(@userid int, @company int) returns bit as
begin
return
    case when exists (
    select * from usertable
    where companyid=@company and isprimaryuser=1 and userid<>@userid)
    then 1 else 0 end
end

ПРОВЕРЬТЕ ограничение

alter table usertable add constraint usertable_ck1
check (isprimaryuser=0 or dbo.anyprimaryuser(userid,companyid)=0)

Тесты

insert usertable select 9,2,1 -- fail

insert usertable select 9,2,0 -- ok

insert usertable select 19,4,1 union all select 20,4,0 -- ok

insert usertable select 19,3,1 union all select 20,3,0 union all select 21,3,1
-- not ok, accepting the multi-row insert will breach the constraint

update usertable set IsPrimaryUser=1-IsPrimaryUser where CompanyId=4
-- ok! sets one and unsets the other in one go

(примечание) Я обновил ответ после комментария Мартина ниже

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