双向关系(数据库设计缺陷)

时间:2011-03-09 11:10:58

标签: database database-design

我有两个表通过一对多的关系相互连接。 问题是引用的表还有第二个表的外键!

我知道这很令人困惑,所以我会告诉你一个简单的数据库设计:

作者

AuthorId      Name       DefaultBookId (FK)
--------      -------    -------------
1             John       1
2             Mike       3
3             Mig        5

图书

BookId        Title            AuthorId (FK)
--------      -------          -------------
1             TitleInfo1       1
2             TitleInfo2       3
3             TitleInfo3       2
4             TitleInfo4       1
5             TitleInfo5       3
6             TitleInfo6       3
7             TitleInfo7       1

当然我必须将books表中的AuthorId作为外键,这是正常情况,但现在我需要为每个作者设置一个默认书,所以我将在一个外键上定义一个外键。新列(DefaultBookId)为每个作者指定默认书。

现在,两个表都相互依赖,所以我不能删除任何项目,除非我删除它们之间的关系,它感觉不对!

关于此设计是否存在缺陷的任何想法以及我该怎么办?

3 个答案:

答案 0 :(得分:2)

我会用第三个表连接另外两个表来实现它。你最终会得到:

<强>作者

AuthorId      Name   
--------      -------
1             John   
2             Mike   
3             Mig    

<强> DefaultBook

AuthorId      DefaultBookId (FK)
--------      -------------
1             1
2             3
3             5

<强>图书

BookId        Title            AuthorId (FK)
--------      -------          -------------
1             TitleInfo1       1
2             TitleInfo2       3
3             TitleInfo3       2
4             TitleInfo4       1
5             TitleInfo5       3

通过对DefaultBook.AuthorId设置UNIQUE约束,可以防止每个作者拥有多个默认值。如果您需要删除作者,只需删除其默认值以及与他相关的任何书籍,即可删除作者。

这有一个问题是很难强制每个作者都有一本默认书,但这个要求是导致你首先遇到这个问题的原因。

答案 1 :(得分:1)

您可以从作者中删除DefaultBookId,向图书添加IsDefaultForAuthor列,然后应用约束,以便每位作者只有一本标记为IsDefaultForAuthor的图书。

当然,这并不能解决由多位作者撰写的书籍等问题,但我假设这是您正在展示的玩具示例,而不是您的实际系统建模。

答案 2 :(得分:1)

原则上这个设计没问题,但当然你已经在实践中发现了一个问题。

以下是您可以尝试的一些事项:

  • 如果您的数据库支持它(oracle确实),则会延迟您的约束。这只会检查提交的约束,因此您可以在一个事务中删除一本书及其作者。 (con:非常特定于数据库)

  • 而不是authors.defaultBookId使用books.isAuthorsDefaultBook。 (con:很难为每个作者强制执行一个默认书;应该可以使用基于功能的索引索引和/或物化视图,这可能是db dependend)

  • 删除defaultBookId上的not null约束并信任你的应用程序正确执行(con:失去数据库的某些功能)

澄清:

删除defaultBookId上的not null约束允许将其设置为null,删除以前引用的书,然后删除作者。对于创作相同的作品,但顺序相反。