10

我的应用程序具有可属于组的用户的通知设置。组管理员可以为整个组定义设置,以便在任何用户执行操作时通知管理员。管理员还可以为单个用户定义设置,这将覆盖组设置。

现在我有一个包含列的数据库:group_id, action1, action2, action3, .... 这些操作是布尔值,用于确定管理员在其组中的用户执行该操作时是否收到通知。

我可以创建一个由 User 模型而不是 Group 模型拥有的单独表,但是将完全相同的数据存储在一个完全独立的表中感觉效率很低,除非group_iduser_id.

另一种选择是添加user_id到我已经拥有的表中,并允许group_id. 在确定用户的通知设置时,应用程序将首先根据用户选择设置,然后回退到group_id不为空的设置。这感觉效率很低,因为数据库中会有很多空值,但它肯定需要我做的工作更少。

对于这种情况,有没有比我描述的两种更有效的设计?

4

2 回答 2

22

通常,有两种策略来处理这样的情况:

1. 使用独占 FK

本质上,每个可能的父表在子表中都有自己的、单独的外键,并且有一个 CHECK 强制其中一个是非 NULL 的。由于 FK 仅对非 NULL 字段强制执行,因此只会强制执行其中一个 FK。

例如:

在此处输入图像描述

(省略用户和组之间的关系)

CHECK (
    (group_id IS NOT NULL AND user_id IS NULL)
    OR (group_id IS NULL AND user_id IS NOT NULL)
)

2.使用继承

从通用超类型继承用户和组,然后将设置连接到超类型:

在此处输入图像描述

有关继承(又名类别、子类化、子类型、泛化层次结构等)的更多信息,请查看ERwin 方法指南的“子类型关系”一章。不幸的是,现代 DBMS 本身并不支持继承——关于物理实现它的一些想法,请查看这篇文章

这是一个重型解决方案,可能仅适用于两个表(组和用户),但对于许多表来说是相当“可扩展的”。

于 2012-11-09T23:21:28.650 回答
0

一个 Actions 表怎么样?

它可能有以下列:

Table Actions:
ActionId - Identity columns
Action   - Store your action here; type would depend on your system
RefId    - The Id for either the user or the group
RefTable - either User or Group

然后在访问表时,您已经知道您的 ID,并且您知道它是组还是用户,然后可以获得适当的操作。

这有意义吗?

更新:

如果您可能对两个用户/组执行相同的操作并希望一个优先级(正如您在 Q 中提到的那样),您还可以添加一priority列并将其设置为tinyInt- 较低的数字 = 较高的优先级。然后,当您选择操作时,您可以按此优先级对它们进行排序。然后执行第一个动作,或按顺序执行每个动作。

于 2012-11-09T17:42:23.287 回答