1

在我试图建模的多对多关系中,我有一种非此即彼的情况。

所以我有这些表:

Message
----
*MessageID
MessageText

Employee
----
*EmployeeID
EmployeeName

Team
----
*TeamID
TeamName

MessageTarget
----
MessageID
EmployeeID (nullable)
TeamID (nullable)

因此,aMessage可以有一个Employees 列表,也可以有一个 s 列表Team作为 a MessageTargetMessageTarget我上面的表格是实现这种关系的最佳方式吗?我可以有效地施加哪些限制MessageTarget?我应该如何在表上创建主键MessageTarget

有问题的数据库是 SQL Server 2008

4

6 回答 6

3

你呈现这个的方式,似乎Employee is-a MessageTargetTeam is-a MessageTarget
所以 aMessage有 aTarget要么是a 要么是Employeea Team
在我看来,这就像 SQL 中的继承(或组合)问题。
查看“在 SQL Server 中实现表继承”。An本身Employee不是一个MessageTarget,但也许这方面的读数可以帮助您进行建模

于 2012-08-27T21:55:48.850 回答
3

因此,您要确保单个消息的 MessageTargets 都设置了 employeeID 或 teamID,但不是两者的混合?

根据您的 RDBMS,您可能能够创建物化视图并对其施加约束。视图看起来像

select messageId, count(employeeId), count(teamId) from messageTarget

在此之上,您将放置一个检查约束,以确保其中一个计数为零。

或者,您可以将 MessageTarget 替换为两个表:EmployeeMessageTarget 和 TeamMessageTarget,每个表在第一个表中只包含一个 TargetId 和一个 EmployeeId,在第二个表中包含一个 TeamId。

您的 Message 表将获得两个新字段:一个 EmployeeMessageTargetId 和一个 TeamMessageTargetId 加上一个检查约束,确保其中至少一个为空。如果您使两个字段都唯一,则可以从 *MessageTarget 表中获得一个外键。

于 2012-08-28T04:26:46.630 回答
2

由于员工和团队不能混合在同一条消息中,您需要执行以下操作:

在此处输入图像描述

  • MessageEmployee.MessageIdForEmployee参考资料Message.MessageIdForEmployee
  • MessageTeam.MessageIdForTeam参考资料Message.MessageIdForTeam

并且表上有以下约束Message

CHECK (
    (MessageIdForEmployee = MessageId AND MessageIdForTeam IS NULL)
    OR
    (MessageIdForEmployee IS NULL AND MessageIdForTeam = MessageId)
)

请注意我们如何为每种子表创建一个单独的联结表,并且联结表引用父级的 PK。相反,每个联结表都引用一个单独的UNIQUE 字段。由于这些字段中只有一个可以为非 NULL,因此只有一种子项可以连接到任何给定消息。

MessageId注意:与MessageIdForEmployeeor匹配并不是绝对必要的MessageIdForTeam,但它可以在一定程度上简化查询。

于 2012-08-28T15:50:24.050 回答
1

你也可以考虑

MessageTarget
----
MessageID
targetID (not nullable)
targetType

然后将类型设置为应为的类型...

于 2012-08-27T21:52:16.690 回答
1

is-a 关系通常是 gen-spec 模式的实例。类表继承是为 gen-spec 的情况设计表的一种方法。

http://martinfowler.com/eaaCatalog/classTableInheritance.html

于 2012-08-28T00:59:56.917 回答
0

考虑删除 MessageTarget 实体中的“团队 ID”字段,以便您只有 messageId 和 employeeId。为了满足团队的需求(如果要求每个员工必须是团队的成员),您可以拥有另一个实体“团队消息”,其中数据库触发器将确保在插入该表时,您可以插入一个团队中每个员工的消息目标表中的行。这样,您可以方便地从每条消息链接回 MessageTarget 表中的员工或返回“团队消息”表中的团队。还将在 ORM 框架中提供方便的访问,其中 Employee 实体仅具有 List 并且 Team 也具有相同的

于 2012-08-28T04:12:14.397 回答