这是我的玩具设置。我有3张桌子。一张桌子是客人名单(姓氏,名字,等等),食物清单(豆类,糊状,米饭,蔬菜)和订单清单(客人ID,食品ID)。订单清单是我感兴趣的清单。我想限制它以满足以下条件。
客人必须拥有3个订单。 客人可以订购空订单。 除非订单为空,否则每位客人的订单不能相同。
因此订单表看起来如下(使用字符串而不是fk ID):
steve, beans
steve, rice
steve, veggies
joey, rice
joey, beans
joey, <null>
sarah, rice
sarah, <null>
sarah, <null>
sam, <null>
sam, <null>
sam, <null>
显然Sam不喜欢食物......但那将是一张有效的餐桌。每个用户都有3个条目,没有用户有重复项(没有双重bean!)。
我尝试过的事情
create table order (
guest_uid FK,
food_uid FK,
CONSTRAINT order_unique UNIQUE (guest_uid, food_uid)
)
这适用于验证没有双豆,但是double / triple null不会飞。我希望oracle unique null适用于此处,但我猜不会(违反了唯一约束order_unique)。
我尝试了一些其他检查约束,但我无法找到一种方法来指定跨行的唯一性而不执行子查询(当然不允许)。有什么想法吗?感谢
PS。如果唯一有效的答案是“使用PL / SQL或触发器”,我将确保标记正确的答案。
答案 0 :(得分:4)
您可以使用基于函数的索引来强制跨行的唯一性(请注意,我调用了表guest_food
,因为order
是保留字
create unique index idx_order_unique
on guest_food( case when food_uid is not null
then guest_uid
else null
end,
case when food_uid is not null
then food_uid
else null
end );
这将允许您为任何特定NULL
添加food_uid
guest_uid
的行数,同时禁止重复的非NULL值。
要求每个guest虚拟机在guest_food
表中只有三行,这不是您可以使用约束强制执行的操作。您可以创建一个物化视图,在提交时执行快速刷新,存储每guest_uid
个行数的计数,并添加一个约束,如果该计数不是3,则会引发错误。但这通常是想要强制实施这一点非常不寻常,所以它会让我怀疑数据模型有点偏差。
答案 1 :(得分:1)
您是否考虑过更改数据结构?由于订单中只有三个项目,因此转动项目:
create table order
(
guest_uid FK,
food_uid1 FK,
food_uid2 FK,
food_uid3 FK
)
然后,您可以为每个food_uid
添加约束,以确保外键正确。
然后,您可以添加一个检查约束,以满足除NULL之外没有重复的要求。