2

这是我的玩具设置。我有 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>

显然山姆不喜欢食物……但那将是一张有效的桌子。每个用户都有 3 个条目,并且没有用户有重复项(你没有双 bean!)。

我尝试过的事情

create table order (
  guest_uid FK,
  food_uid FK,
  CONSTRAINT order_unique UNIQUE (guest_uid, food_uid)
)

这适用于验证没有双 bean,但双/三空不会飞。我希望 oracle 唯一的 null 可以在这里应用,但我猜不是(违反了唯一约束 order_unique)。

我尝试了其他一些检查约束,但我无法找到一种方法来指定跨行的唯一性而不执行子查询(当然,这是不允许的)。有什么想法吗?谢谢

附言。如果唯一有效的答案是“使用 PL/SQL 或触发器”,我会确保将其标记为正确答案。

4

2 回答 2

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 值的同时,NULL food_uid为任何特定的行拥有尽可能多的行。guest_uid

每个客人在表中恰好有三行的要求guest_food不是您可以通过约束强制执行的。您可能会创建一个物化视图,该视图在提交时进行快速刷新,该视图存储每个行数的计数,guest_uid并添加一个约束,如果该计数不是 3,则会引发错误。但这通常是一件相当不寻常的事情强制执行,所以它往往会让我怀疑数据模型有点偏离。

于 2012-04-09T19:07:24.950 回答
1

您是否考虑过更改数据结构?由于您的订单中恰好有三个项目,因此旋转这些项目:

create table order 
(
    guest_uid FK,
    food_uid1 FK,
    food_uid2 FK,
    food_uid3 FK
) 

然后,您可以为每个添加约束food_uid以确保外键正确。

然后,您可以添加一个检查约束以满足您对除 NULL 之外没有重复项的要求。

于 2012-04-09T19:08:14.437 回答