假设:一个用户可以通过一个接口插入输入,输入是关于一种食物,用来喂养特定的猫或狗。
在userinput表中,我们想要保存foodid和我们正在谈论的猫或狗的id。
我们有价值观,但是:
如果subject是catid,我们如何检查它是否存在于de cats表中。
如果主语是dogid,我们如何检查它是否存在于de dogs表中。
我想到了下面的解决方案,但我得到'子查询在这种情况下是不允许的。只允许使用标量表达式。'
CONSTRAINT checksubject CHECK (
EXISTS (SELECT 1 FROM cats c WHERE c.catid = subjectid) AND (SELECT categoryid FROM foods f WHERE f.foodid = userinput.foodid) = 0
OR
EXISTS (SELECT 1 FROM dogs d WHERE d.dogid = subjectid) AND (SELECT categoryid FROM foods f WHERE f.foodid = userinput.foodid) = 1
)
3条答案
按热度按时间1tu0hz3e1#
你不能(容易地)用check约束做你想做的事。你有一个相当复杂的依赖关系。
两种可能的解决方案是:
创建执行检查的用户定义函数。尽管你不能把复杂的逻辑放在
check
约束,可以调用用户定义的函数。使用触发器。
或者,可以重新构造数据模型以包含
categoryid
麻烦userinput
以及foods
. 可以使用外键约束和计算列来表示此子集关系。对于此解决方案,您将从食物的冗余唯一索引/唯一约束开始:
然后添加
categoryid
至userinput
:外键引用确保值相同。
然后添加持久化计算列:
最后添加外键约束:
请注意,持久化列确实占用了空间。但这允许您拥有“条件”外键约束,而无需使用自定义代码(即触发器或udf)。
umuewwlo2#
我不相信你有条件外键。根据您的要求,可能还有其他方法可以做到这一点。
向userinput表添加两个可为null的列,一个用于catid,另一个用于dogid。添加一个约束以确保其中一个为null,而不是同时为null。
猫和狗都放在动物桌上,桌上有一列标明动物种类。
将userinput拆分为catuserinput和doguserinput
您将真正需要检查您的用例以确定最佳方法。例如,如果您真的必须将猫和狗分为两个表,那么您就是在建模猫/狗和食物之间的多对多关系。
xeufq47z3#
狗和猫是宠物的特长。换句话说,狗和猫是宠物的一个子类。你可以为宠物准备一张table,上面有一个指示栏,标明是猫还是狗。该表的键petid现在可以用作外键。