适当的数据结构,以保持一对多的关系

时间:2010-09-03 03:00:27

标签: php sql mysql database-design schema

我想在数据库中表示文档。有几种不同类型的文件。所有文件都有一些共同点,但并非所有文件都相同。

例如,假设我有一个基本的文档表...

TABLE docs (
    ID
    title
    content
)

现在假设我有一个可以属于用户的文档子集,并且可以有与之关联的其他信息。我可以做以下......

TABLE docs (
    ID
    userID -> users(ID)
    title
    content
    additionalInfo
)

...但是这会导致表中有很多空值,因为只有某些文档可以属于用户,而不是全部。因此,我创建了第二个表“ownedDocs”来扩展“docs”:

TABLE ownedDocs (
    docID -> docs(ID)
    userID -> users(ID)
    additionalInfo
)

我想知道:这是正确的方法吗? (我很担心,因为虽然一切都在一个表中,但我在文档和用户之间有一对多的关系。但是,通过创建一个新的表ownedDocs,数据结构看起来像我在docs之间有多对多的关系和用户 - 永远不会发生。)

提前感谢您的帮助

3 个答案:

答案 0 :(得分:3)

  

数据结构看起来我在文档和用户之间存在多对多的关系 - 这种情况永远不会发生。

理解后,您需要在docs表中使用userid以确保一对多关系(一个用户,可能是多个文档)。

如果文档未与特定用户关联,userid列为空,则我没有看到其他信息列中的损害为空。将附加信息拆分到另一个表仍然意味着一对一的关系,因此您最好使用一个包含doc,user和其他信息的表...

答案 1 :(得分:2)

  

“通过创建一个新的表ownedDocs,   数据结构看起来像我有一个   docs之间的多对多关系   和用户 - 这将永远不会发生。)“

如果你使OwnedDocs.DocId成为主键,那么很明显1:N关系是不可能的。

零或一对一关系的建模是棘手的。如果我们只有一个子类型,那么具有NULL列的单个表是一种合理的方法。但是,最好确保仅在适当时填充子类型属性。在给定的示例中,这意味着检查约束以强制执行此规则:

check (userID is not null or AdditionalInfo is null)

或者甚至可能是这条规则:

check ( (userID is not null and AdditionalInfo is not null)
        or (userID is null and AdditionalInfo is null) )

属性之间的关系不会显示在ERD中(除非您使用命名约定)。当然,在第二种情况下,所拥有文件的AdditionalInfo的强制性质并不明显。

一旦我们有几个这样的子类型,单独表格的情况就变得很有吸引力,特别是如果子类型构成弧形,例如文档可以是FinancialDocument,也可以是MedicalDocument或PersonnelDocument,但不能超过一个类别。我曾经使用一个包含大量空列,视图和检查约束的表来实现这样的模型。那太差了。子类型表肯定是要走的路。

答案 2 :(得分:1)

这取决于您想要达到的normalization级别。通常,根据您提供的描述,我会像这样构建我的数据库:

table docs (id, title, content);
table users (id, ...);
table users_docs (doc_id, user_id);
table doc_info(doc_id, additional_info);

如果我错了,有人会纠正我,但这应该是第3范式。这使结构保持良好和干净,并且仅使用按预期存储数据所需的位。您可以独立存储所有元素,但可以根据需要进行相关。

根据附加信息的性质,您需要进行一些更改。例如,附加信息是否总是与用户对应?如果文档与用户关联,是否始终提供?如果是,则可以将其添加到users_docs表中。但这至少应该向你展示规范化。