数据库儿童表与两个可能的父母

时间:2012-10-06 21:31:46

标签: database database-design constraints

首先,我不确定如何搜索这个,所以如果它是重复的,请原谅。我甚至不确定它是否更适合其他StackExchange站点之一;如果是的话,请告诉我,我会在那里问。反正...

项目快速概览

我正在做一个爱好项目 - 一个作家的笔记本 - 来练习编程和数据库设计。基本结构非常简单:用户可以创建笔记本,在每个笔记本下,他们可以创建与该笔记本相关的项目。也许笔记本是一系列短篇小说,每个项目都是针对个人故事。

然后,他们可以将项目(场景,角色等)添加到笔记本中的特定项目或笔记本本身,以便它不与特定项目相关联。这样,他们可以拥有跨越多个项目的场景或位置,以及一些特定于特定项目的场景或位置。

问题

我正在尝试在数据库中保留大量逻辑 - 特别是在表结构和约束内,如果可能的话。我对很多项目的基本结构基本上都是这样的(我正在使用MySql,但这是一个非常普遍的问题 - 只是提到它的语法):

CREATE TABLE SCENES(
    ID        BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
    NOTEBOOK  BIGINT UNSIGNED NULL,
    PROJECT   BIGINT UNSIGNED NULL,
    ....
);

问题是我需要确保设置两个引用中的至少一个,NOTEBOOK和/或PROJECT。它们不必同时设置 - PROJECT引用它所在的NOTEBOOK。我知道我可以只有一个通用的“Parent Id”字段,但我不相信它有可能有一个外来的两张桌子的关键,对吗?还有可能添加额外的交叉引用表 - 即SCENES_X_NOTEBOOKS和SCENES_X_PROJECTS - 但是这很快就会失控,因为我必须为我正在工作的每种不同的项目类型添加类似的表用。这也会引入确保每个项目在交叉引用表中都有条目的问题。

将这种逻辑放在存储过程或应用程序逻辑中很容易,但是如果可能的话,我真的希望将它保留在某种约束中,以消除任何可能性逻辑绕过了一些方法。

有什么想法?我对几乎任何事情都很感兴趣 - 即使它涉及重新设计表格等等。

2 个答案:

答案 0 :(得分:3)

关于场景和角色的事情是作家可能会将他们从当前项目中删除。当发生这种情况时,你不想丢失场景和角色,因为作家可能决定在几年后使用它们。

我认为最简单的方法是重新定义:

  

然后他们可以将项目(场景,角色等)添加到a   笔记本内的具体项目,或笔记本本身   它与特定项目无关。

而不是那样,想想这样说。

  

然后他们可以将项目(场景,角色等)添加到a   笔记本中的用户定义项目,或系统定义的项目   项目名为“未分配”。项目“未分配”不是为了事情   目前已分配给用户定义的项目。

如果这样做,那么场景和角色将始终分配给项目 - 或者分配给用户定义的项目,或者分配给名为“未分配”的系统定义的项目。

答案 1 :(得分:2)

我不清楚你的要求是什么,但至少让我试着回答你的一些问题......

  

问题是我需要确保设置两个引用中的至少一个,NOTEBOOK和/或PROJECT。

检查(笔记本不是空或项目不是空)

  

我不相信有两张表的外键,对吗?

理论上,您可以从同一个字段引用两个表,但这意味着这两个表中的必须包含匹配的行。这可能不是你想要的。

你在这里是正确的轨道 - 让NOTEBOOK成为FK朝向一个桌子的子终点,PROJECT朝向另一个桌面。不会强制使用NULL外键,因此您不必同时设置它们。

  

还有可能添加额外的交叉引用表 - 即SCENES_X_NOTEBOOKS和SCENES_X_PROJECTS - 但这很快就会失控,因为我必须为每种不同的项目类型添加类似的表格和我一起工作。

如果你在讨论模拟多对多关系的联结(aka .link)表,那么是 - 你必须为参与这种关系的每对表添加它们。

但是,您可以使用继承(也就是类别,子类,子类型,泛化层次结构......)来最小化此类表对的数量。想象一下,你有一组M表必须连接到第二组N表。通常,您已经创建了M * N联结表。但是,如果从公共父表继承第一组中的所有表,并对第二组执行相同操作,则现在可以通过这两个父表之间的一个联结表将它们全部连接起来。

关于继承的完整讨论超出了这里的范围,但您可能希望查看"ERwin Methods Guide",“子类型关系”一章以及this post

  

将这种逻辑放在存储过程或应用程序逻辑中很容易,但是如果可能的话,我真的希望将它保留在某种约束中,以消除任何可能性逻辑绕过了一些方法。

你的直觉是正确的 - 让数据库尽可能地从坏数据中“保护”自己。以下是确保数据正确性的偏好顺序

  • 表格本身的结构。
  • 声明性数据库约束(域的完整性,密钥的完整性和参照完整性)。
  • 触发器和存储过程。
  • 中间层。
  • 客户端。

例如,如果您只需使用声明性数据库约束就可以确保必须遵循某个逻辑,则不要将其放在触发器中。

相关问题