use*_*679 2 foreign-key database-design sql-server referential-integrity
可能我的设计是错误的,或者只是有更好的方法。我将使用一个非常简单的例子:
--------- dbo.Book----------
| |
| BookID int identity (1,1) |
| ShelfID int FK |--
---------------------------- |
|
--------- dbo.Row----------- |
| | |
--| RowID int identity (1,1) | |
| ---------------------------- |
| |
| -------- dbo.Shelf---------- |
| | | |
| | ShelfID int identity (1,1)|--
--| RowID int FK |
----------------------------
Run Code Online (Sandbox Code Playgroud)
足够简单。
但是如果我想分配一个没有架子的行怎么办?也许我们还知道行而不是货架:
--------- dbo.Book----------
| |
| BookID int identity (1,1) |
| RowID int FK | <-- New
| ShelfID int FK NULL |
----------------------------
Run Code Online (Sandbox Code Playgroud)
有没有更好的设计方法呢?我需要确保ShelfID和RowID自己各自的父/子表匹配。
最好的方法是什么?调用函数的约束?好像很贵 不同的表结构?我可能会遗漏一些非常简单明显的东西。
细化:
如果dbo.Shelf具有以下值:
[ShelfID] [RowID]
------------------
3 1
Run Code Online (Sandbox Code Playgroud)
然后我们应该期望该dbo.Row表具有一个值为 1 的主键。我希望该表具有相同的参照完整性dbo.Book:
[BookID] [RowID] [ShelfID]
--------------------------
1 1 3
Run Code Online (Sandbox Code Playgroud)
我该如何强制执行?称为约束的函数是最好的方法吗?还是我的设计有问题?
如果Book表中存在两个值,我的要求是维护数据完整性。其他两个表中必须存在相关关系。也许我把它复杂化了,调用函数的检查约束是要走的路。
我知道能够将 FK 设置为 null。基本上,如果ShelfID和RowID两者在主Book表中都有一个值,那么确保它RowID和ShelfID匹配的最佳方法是什么?ShelfID必须存在于dbo.Shelf表中,那一个很容易。但是RowIDinBook表必须是在dbo.Shelf.
确保 aShelfID和RowID不要最终出现在Book虚假关系表中的最佳方法是什么?例如 ,RowID = 1和ShelfID = 3,但是在Shelf表中,没有这样的关系。
你需要两件事:
从Book该引用中添加一个额外的外键Row。
从修改外键Book,以Shelf使它包含RowID并成为一个外键:(RowID, ShelfID) REFERENCES Shelf (RowID, ShelfID)。这是为了对齐 2 个外键。否则,您最终可能会得到一个Bookthat 引用RowID = 1,ShelfID = 33而 whileShelf 33正在引用RowID = 2.
此外 - 要使上述修改成功 - 您需要UNIQUE在 Shelf 上添加约束(RowID, ShelfID)。或者,您可以修改Shelf主键。
除了Book.ShelfID. 有一种方法可以让所有列不为空,但它需要一个额外的表。
表变成:
--------- dbo.Row-----------
| |
--| RowID int PK |-----
| ---------------------------- ^
^ |
| |
| -------- dbo.Shelf---------- ^
^ | |-- |
FK| | ShelfID int PK UQ1 | | |
--| RowID int FK UQ1 | | ^
---------------------------- ^ |
| |
FK1| ^
--------- dbo.Book---------- ^ |
| |--| |
| BookID int PK | ^FK2
| RowID int FK1 FK2 |-----|
| ShelfID int FK1 |
----------------------------
Run Code Online (Sandbox Code Playgroud)