Sql-Server

當兩個 FK 列需要在同一個表中匹配自己時的引用完整性?

  • April 29, 2017

可能我的設計是錯誤的,或者有更好的方法。我將使用一個非常簡單的範例:

   --------- 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       | 
   ---------------------------- 

有沒有更好的設計方法呢?我需要確保ShelfIDRowID在他們各自的父/子表中匹配。

最好的方法是什麼?呼叫函式的約束?好像很貴 不同的表結構?我可能會遺漏一些超級簡單的東西。

闡述:

如果dbo.Shelf具有以下值:

[ShelfID]  [RowID]
------------------
3          1

然後我們應該期望該dbo.Row表有一個值為 1 的主鍵。我希望該表具有相同的參照完整性dbo.Book

[BookID] [RowID] [ShelfID]
--------------------------
1        1       3

我該如何執行?函式呼叫約束是最好的方法嗎?還是我的設計錯了?

Book如果兩個值都存在於表中,我的要求是維護數據完整性。其他兩個表中必須存在關聯關係。也許我已經把它複雜化了,一個呼叫函式的檢查約束是要走的路。

我知道能夠將 FK 設置為 null。基本上,如果ShelfID兩者RowID在主Book表中都有一個值,那麼確保RowIDShelfID匹配的最佳方法是什麼?ShelfID必須存在於dbo.Shelf表中,那很容易。但是RowIDinBook表必須是在 中找到的同一個父級dbo.Shelf

確保一個ShelfID並且RowID不會出現在Book表中的最佳方法是什麼是錯誤的關係?例如RowID = 1, 和ShelfID = 3, 但在Shelf表中,沒有這樣的關係。

你需要兩件事:

  • Book該引用中添加一個額外的外鍵Row
  • 將外鍵從 to 修改為Book包含ShelfRowID成為複合外鍵:(RowID, ShelfID) REFERENCES Shelf (RowID, ShelfID). 這是為了對齊 2 個外鍵所必需的。否則,您最終可能會得到 a Bookthat referencesRowID = 1ShelfID = 33while Shelf 33is references 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        |
       ----------------------------   

引用自:https://dba.stackexchange.com/questions/172304