0

我希望在 RDBMS 中模拟一个有多个提议时间的会议,但其中一个将被选为接受的或主要的。就像是:

create table Meeting ( meetingId int );
create table ProposedTime( meetingId int, dateAndTime datetime );

但是,将有一个界面,用户可以在其中选择一个建议的时间,我需要保存该选择。

我可以想到两个选项,每个选项都有缺点:

  1. 在会议表中保留选定的提案:

    create table Meeting( meetingId int, selectedProposalId int );
    create table ProposedTime( proposalId int PK, meetingId int, dateAndTime datetime );
    

    使用这种方法, selectedProposalId 可能用于属于不同会议的提案。

  2. 在所选提案上存储一个标志:

    create table Meeting(meetingId int);
    create table ProposedTime( meetingId int, dateAndTime datetime, isSelected bool );
    

    使用这种方法,可以将两个提案标记为选中。

我知道有“黑客”来确保完整性(对于 2,在 MS SQL 中你可以有一个过滤的唯一索引来确保只选择一个),但我宁愿不承诺供应商特定的代码。

我也可以只在应用程序层强制执行正确性,但这仍然让两个选项都打开。

大家有什么推荐的?如果有人有任何想法,我也愿意接受其他选择;)

注意:我使用的是 Rails 3,所以如果有使用 ActiveRecord 处理此问题的首选方法,我想听听。

4

1 回答 1

1

好问题。我喜欢你正在评估潜在的不一致的事实。在这种情况下,我认为第一个解决方案是正确的,只是做了一个小的修改:ProposedTime 的主键应该是包含 meetingId 的复合主键。

这有几个原因:首先,一个proposedTime显然不能没有会议,更重要的是它不能没有特定的会议。从本质上讲,proposedTime 只能在会议的上下文中定义,因此它的定义不应允许它独立存在。

其次,使用 meetingId 作为强制属性时,这种依赖关系没有得到充分表达。例如,更新提议时间的 meetingId 字段是没有意义的。“让我们把上午 9 点搬到另一个会议!”。将 meetingId 作为主键的一部分明确地阻止了这种无意义的更新,因为更新的主键本质上是不同的东西。

最后,proposedTime 具有逻辑上不完整的键这一事实是您在尝试正确使用它时遇到的第一件事。理想情况下,每个数据库关系都应该声明式一致。也就是说,如果你可以表达“狮子有两个父母”的关系,那么一个父母应该不可能是松鼠。显然,性能和平台限制意味着您不能总是达到那个目标,但是这种不一致可以被视为“代码气味”,可能需要进一步调查。在您的情况下,该修复程序似乎很小且性能良好。

tl;dr:将 meetingId 添加到建议时间的 PK 中,然后使用您的第一个解决方案。

于 2011-04-28T20:04:54.000 回答