Sql-Server
當兩個 FK 列需要在同一個表中匹配自己時的引用完整性?
可能我的設計是錯誤的,或者有更好的方法。我將使用一個非常簡單的範例:
--------- 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 | ----------------------------
很簡單。
但是如果我想分配一個沒有貨架的行怎麼辦?也許我們知道行但還不知道架子:
--------- dbo.Book---------- | | | BookID int identity (1,1) | | RowID int FK | <-- New | ShelfID int FK NULL | ----------------------------
有沒有更好的設計方法呢?我需要確保
ShelfID
並RowID
在他們各自的父/子表中匹配。最好的方法是什麼?呼叫函式的約束?好像很貴 不同的表結構?我可能會遺漏一些超級簡單的東西。
闡述:
如果
dbo.Shelf
具有以下值:[ShelfID] [RowID] ------------------ 3 1
然後我們應該期望該
dbo.Row
表有一個值為 1 的主鍵。我希望該表具有相同的參照完整性dbo.Book
:[BookID] [RowID] [ShelfID] -------------------------- 1 1 3
我該如何執行?函式呼叫約束是最好的方法嗎?還是我的設計錯了?
Book
如果兩個值都存在於表中,我的要求是維護數據完整性。其他兩個表中必須存在關聯關係。也許我已經把它複雜化了,一個呼叫函式的檢查約束是要走的路。我知道能夠將 FK 設置為 null。基本上,如果
ShelfID
兩者RowID
在主Book
表中都有一個值,那麼確保RowID
並ShelfID
匹配的最佳方法是什麼?ShelfID
必須存在於dbo.Shelf
表中,那很容易。但是RowID
inBook
表必須是在 中找到的同一個父級dbo.Shelf
。確保一個
ShelfID
並且RowID
不會出現在Book
表中的最佳方法是什麼是錯誤的關係?例如RowID = 1
, 和ShelfID = 3
, 但在Shelf
表中,沒有這樣的關係。
你需要兩件事:
- 從
Book
該引用中添加一個額外的外鍵Row
。- 將外鍵從 to 修改為
Book
包含Shelf
並RowID
成為複合外鍵:(RowID, ShelfID) REFERENCES Shelf (RowID, ShelfID)
. 這是為了對齊 2 個外鍵所必需的。否則,您最終可能會得到 aBook
that referencesRowID = 1
和ShelfID = 33
whileShelf 33
is referencesRowID = 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 | ----------------------------