Database 双向关系(数据库设计缺陷)
我有两个表,它们通过一对多的关系相互连接。 问题是引用的表也有第二个表的外键 我知道这很混乱,所以我将向您展示我的数据库的一个简单设计: 作者Database 双向关系(数据库设计缺陷),database,database-design,Database,Database Design,我有两个表,它们通过一对多的关系相互连接。 问题是引用的表也有第二个表的外键 我知道这很混乱,所以我将向您展示我的数据库的一个简单设计: 作者 AuthorId Name DefaultBookId (FK) -------- ------- ------------- 1 John 1 2 Mike 3 3 Mig 5 BookId
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
AuthorId Name
-------- -------
1 John
2 Mike
3 Mig
BookId Title AuthorId (FK)
-------- ------- -------------
1 TitleInfo1 1
2 TitleInfo2 3
3 TitleInfo3 2
4 TitleInfo4 1
5 TitleInfo5 3
书籍
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
AuthorId Name
-------- -------
1 John
2 Mike
3 Mig
BookId Title AuthorId (FK)
-------- ------- -------------
1 TitleInfo1 1
2 TitleInfo2 3
3 TitleInfo3 2
4 TitleInfo4 1
5 TitleInfo5 3
当然,我必须将books表中的
AuthorId
设置为外键,这是正常情况,但现在我需要为每个作者设置一个默认书籍,因此我将在新列(DefaultBookId)
上定义一个外键,以指定每个作者的默认书籍
现在,这两个表相互依赖,所以我不能删除任何项目,除非我删除它们之间的关系,而且我觉得这样做不对
关于这个设计是否有缺陷,我能做些什么 您可以从作者中删除
DefaultBookId
,向书籍添加IsDefaultForAuthor
列,然后应用约束,使每个作者只有一本书标记为IsDefaultForAuthor
当然,这并不能解决诸如由多个作者撰写的书籍之类的问题,但我假设这是您正在展示的一个玩具示例,而不是您正在建模的实际系统。原则上,这种设计是可以的,但您当然已经在praxis中发现了一个问题 以下是一些您可以尝试的东西:
- 如果您的数据库支持它(oracle支持),则会延迟约束。这将只检查提交时的约束,因此您可以在一个事务中删除一本书及其作者。(反对:非常特定于数据库)
- 使用books.isAuthorsDefaultBook代替authors.defaultBookId。(缺点:很难强制每个作者只执行一本默认书;应该可以使用基于函数的索引和/或物化视图,这可能依赖于数据库)
- 删除defaultBookId上的NOTNULL约束,并相信您的应用程序能够正确地执行此操作(缺点:失去数据库的某些功能)
删除defaultBookId上的NOTNULL约束可以将其设置为null,删除以前引用的书籍,然后删除作者。创建相同的工作,但顺序相反。我将使用第三个表来实现这一点,该表连接其他两个。你最终会得到: 作者
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
AuthorId Name
-------- -------
1 John
2 Mike
3 Mig
BookId Title AuthorId (FK)
-------- ------- -------------
1 TitleInfo1 1
2 TitleInfo2 3
3 TitleInfo3 2
4 TitleInfo4 1
5 TitleInfo5 3
DefaultBook
AuthorId DefaultBookId (FK)
-------- -------------
1 1
2 3
3 5
书籍
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
AuthorId Name
-------- -------
1 John
2 Mike
3 Mig
BookId Title AuthorId (FK)
-------- ------- -------------
1 TitleInfo1 1
2 TitleInfo2 3
3 TitleInfo3 2
4 TitleInfo4 1
5 TitleInfo5 3
通过在DefaultBook.AuthorId
上设置唯一约束,可以防止每个作者拥有多个默认值。如果您需要删除作者,只需删除其默认设置和与之关联的任何书籍,即可删除该作者
这其中的一个问题是,很难强制每个作者都有一本默认的书,但这一要求首先导致了这个问题。我不会面对多个作者,因为你是对的,我只是在一个简单而常见的设计上模拟了我的问题(经典的书和作者示例)。。我已经考虑过了,但我将如何做这一部分:“应用一个约束,使每个作者只有一本书标记为IsDefaultForAuthor”?@IKashef-依赖于数据库(和版本)-在SQL Server中,您将使用过滤索引(2008)或索引视图(关于您的第一个选项,SqlServer支持吗?。很抱歉,我没有得到第三个选项,not null约束与数据库的引用完整性有什么关系,您的意思是放弃FK约束吗?第二个选项似乎是最好、最简单的解决方案,不会给我的设计增加复杂性(我、戴门和你已经考虑过了,这证明了它的简单性)但是很难更改默认书籍的设置,我的意思是,每次我必须更改默认书籍时,我必须连接n次以将IsDefault设置为同一作者下的其他书籍,而且当我获取作者信息而不是仅使用DefaultBookId显示默认书的信息时,我必须循环浏览bo确定并检查IsDefault==true!。您认为如何=)?您可以通过一个update/select语句轻松设置和读取IsDefault值。因此,我认为这里没有太多问题。看起来sql server不支持延迟约束:不敢相信没有人提到这样一个干净的解决方案。。谢谢=)(Y)…但如果你能指出这一点的意思,“这有一个问题是很难强制每个作者都有一本默认的书,但这一要求首先导致了这个问题。”因为我看不出这个解决方案有什么问题!如果它有我看不到的缺点,你能指出它吗out@IKashef-值得考虑的一件事是,无论是这个模型还是您的原始模型都不强制默认书是由默认书的作者编写的(试着说快5倍)。很难说这是否是你实际问题领域的一个问题。@Damien+1《泰晤士报》我认真阅读了你的评论,忍不住大笑哈哈。。我真的在这里尝试!很难把它整合起来:D。。关于你的评论!你的意思是作者的默认书不是他写的吗?。如果是这样,你怎么会这样呢再次检查示例中的表!每个记录都匹配course@IKashef-在您的示例中,每个记录都匹配-但如果这是真正的限制(即,使用您的示例数据,author 1的默认书籍可以是BookID 3吗),我们没有采取任何措施来强制执行该限制