Sql 服务器全局阻止列表和项目特定允许列表

Sql Server Global Blocked List and Item specific Allow List

乍一看这似乎很容易,但在考虑了一天之后我就卡住了。

假设您有一个蔬菜的全局阻止列表。

create table blocked_veggie(veggieid int primary key, veggiename varchar(20))

insert into blocked_veggie(veggieid, veggiename) values(1, 'broccoli')
insert into blocked_veggie(veggieid, veggiename) values(2, 'carrots')

这 table 说晚餐不允许吃这些蔬菜。

但是,还有一个针对特定 child 的覆盖 table 表示此 child 忽略全局块并允许素食。

create table allow_veggie(allowuid uniqueidentifier primary key, veggiename varchar(20), childname varchar(20))

insert into allow_veggie(allowuid, veggiename, childname) values(newid(), 'broccoli', 'Jimmy')

查询如下所示:

declare    @veggie varchar(20) = 'broccoli'
         , @childname varchar(20) = 'Jimmy'

select 1
from blocked_veggie v
where v.veggiename = @veggie

union all

select 1
from allow_veggie a
where a.veggiename = @veggie
and a.childname = @childname

如果在第二个查询中找到匹配项,如何取消第一个查询?换句话说,我希望返回一个空结果集。

我无法将它们组合起来,因为我可能会遇到这种情况...

declare    @veggie varchar(20) = 'broccoli'
         , @childname varchar(20) = null

select 1
from blocked_veggie v
where v.veggiename = @veggie

union all

select 1
from allow_veggie a
where a.veggiename = @veggie
and a.childname = @childname

这里没有child名称,所以没有覆盖全局块。

我认为我们应该在这里使用EXCEPT,而不是UNION

declare    
    @veggie varchar(20) = 'broccoli',
    @childname varchar(20) = 'Jimmy';

select v.veggiename
from blocked_veggie v
where v.veggiename = @veggie

EXCEPT

select a.veggiename
from allow_veggie a
where 
    a.veggiename = @veggie and 
    a.childname = @childname
;

如果 @childname 为 NULL,查询的第二部分将 return 没有行,因为 a.childname = NULL 为假,整个查询将 return 所有来自 blocked_veggie.

的行