Database-Design

使用索引創建與表的多個關係,以加強數據完整性並增加意義

  • July 20, 2012

我正在研究一個使用超類型/子類型模型的庫存數據庫。我的問題是關於使用主鍵和包含主鍵的複合索引與同一個表創建多個關係。範例情況如下。

情況 1 (為簡單起見,已從範例圖中刪除了不必要的欄位)

我有以下表格:Device、DeviceType 和 DeviceCategory。

DeviceCategory Table

CategoryCode | Name        | Description
----------------------------------------
WKS          | Workstation | Description of what classifies an item as a workstation...
LPT          | Laptop      | Description of what classifies an item as a laptop...


DeviceType Table

ID | CategoryCode | Manufacturer | Model  | IsTrackedInOtherSystemDefault
-------------------------------------------------------------------------
1  | WKS          | Dell         | GX1000 | true
2  | LPT          | HP           | dv4000 | false


Device Table

ID | SerialNumber | DeviceTypeID | IsTrackedInOtherSystem | CategoryDiscriminator
---------------------------------------------------------------------------------
1  | I81U812      | 1            | true                   | WKS
2  | N0S4A2       | 1            | false                  | WKS
3  | 3BL1NDMIC3   | 2            | false                  | LPT

圖 1 - 實體關係圖

如果您注意到,我在 ‘s的主鍵DeviceType和’s之間有一個關係,並且我在’s和上也有一個索引,我用它來將 傳播到表以用作子類型表的鑑別器。它還確保and組合實際存在於表中。Device``DeviceType``DeviceTypes``ID``CategoryCode``CategoryCode``Device``CategoryCode``DeviceType ID``DeviceType

您還會注意到Computer子類型表與Device’ 的主鍵有關係,而另一種關係與DeviceIDCategoryDiscriminator欄位上的複合索引有關係。這會傳播鑑別器,因此我可以在 CHECK 約束中使用它來強製表中只允許某些類別的設備。同樣,它還確保CategoryDiscriminatorandID組合實際存在於Device表中。

我對此設置有以下疑問:

  1. 我應該與相同的兩個表建立兩個關係,一個與主鍵,一個與包含主鍵的索引,還是應該只與復合索引建立關係,因為它已經包含主鍵?
  2. 我是否通過創建索引來不正確地使用索引,其唯一目的是建立強制數據完整性的關係?
  3. 我是否過度設計了數據庫?

情況2

在第一個範例 ERDIsTrackedInOtherSystemDefault中,DeviceType表中的欄位是一個布爾值,表示該設備類型是否在我們使用的另一個專門系統中被跟踪。由於各種原因,某些設備可能不會在其他系統中被跟踪,因此我想為使用者提供在進入設備時覆蓋此欄位的功能。如果未提供其他值,則從表中復製表中的IsTrackedInOtherSystem欄位。從中複製預設值將發生在儲存過程中。Device``DeviceType``DeviceType

我不知道將這個功能隱藏在一個過程中是否是一個壞主意,因為其他 DBA 不會直接看到該欄位從何處獲取其預設值。我認為我可以通過使用關係來強制執行它並使其更加可見,這需要另一個索引。請參閱以下 ERD。

圖 2 - 實體關係圖

在此設置中,DeviceType的主鍵和 的複合索引IsTrackedInOtherSystemDefault用於強制執行值的來源,並且它必須是兩個欄位的有效組合。表中的OverrideTrackedDefault欄位Device是另一個布爾值,基本上表示否定預設欄位。我覺得這種設置賦予了它更多的意義,因為從表的創建開始,這些規則就在表中顯而易見,而不是依賴於隱藏在儲存過程中某處的程式碼行。

**更新:**我在這裡真正要問的是:如果一個表中的一個欄位從另一個表中的一個欄位中獲取一個值,這不保證關係嗎?僅將值複製到不可見的儲存過程中似乎是不自然的。

我對此設置有以下疑問:

  1. 與情況 1 相同的問題:問題 1。
  2. 與情況 1 相同的問題:問題 2。
  3. 與情況 1 相同的問題:問題 3。
  4. 雖然情況可能更容易,並且在儲存過程中使用更少的程式碼執行,但如果添加欄位、關係和索引的成本使系統規則更加明顯,那麼是否建議這樣做?

情況1

您的表有一個關係,而不是兩個。(例如: aDevice屬於 a DeviceType

因此,只保留一種關係,即具有復合鍵(包括主鍵)的關係。當定義復合關係時,另一種關係是多餘的。

我還建議您為相關列使用相同的名稱:

DeviceCategory Table
CategoryCode | Name        | Description
----------------------------------------
WKS          | Workstation | Description of what classifies an item as a workstation...
LPT          | Laptop      | Description of what classifies an item as a laptop...

DeviceType Table
DeviceTypeID | CategoryCode | Manufacturer | Model  | IsTrackedInOtherSystemDefault
-----------------------------------------------------------------------------------
1            | WKS          | Dell         | GX1000 | true
2            | LPT          | HP           | dv4000 | false
3            | WKS          | HP           | xx9000 | false

Device Table
DeviceID | SerialNumber | DeviceTypeID | IsTrackedInOtherSystem | CategoryCode 
------------------------------------------------------------------------------
1        | I81U812      | 1            | true                   | WKS
2        | N0S4A2       | 1            | false                  | WKS
3        | 3BL1NDMIC3   | 2            | false                  | LPT

因此,設計將是:

DeviceCategory
--------------
CategoryCode   PK
Name           U1
Description

DeviceType 
----------
DeviceTypeID   PK   U1
CategoryCode   FK   U1
Manufacturer   U2
Model          U2
IsTrackedInOtherSystemDefault

Device 
------
DeviceID       PK   U1
SerialNumber   U2
DeviceTypeID   FK1
IsTrackedInOtherSystem
CategoryCode   FK1  U1

對於Computer

Computer
--------
DeviceID       PK   FK1
Hostname       U1
IPAddress      U2
CategoryCode   FK1  CHK

大多數 DBMS 都需要“附加”UNIQUE鍵(兩個複合鍵U1)來強制執行外鍵約束。我想這回答了你的問題 2,關係需要強制執行索引,所以(你必須)使用它們。DBMS 不僅將使用它們來強製完整性,而且在您將要加入表時在您的查詢/語句中使用它們。

唯一不需要的是U3你在Computer桌子上的那個。

關於問題 3(過度工程部分):不,我不這麼認為,但這只是我的看法。而且你還沒有告訴我們這是一個家庭作業/練習還是一個真正的項目,你是只持有你家人的庫存還是數百萬公司的庫存等等。


情況2

我認為你所擁有的很好,沒有必要(也不是一個好主意)對這些列進行參照完整性約束。這是通過儲存過程複製到第二個表中的預設值(我猜是在第二個表上插入期間?)或由使用者更改。如果您添加 FK,那不會拒絕使用者覆蓋預設值的能力嗎?

這兩列的名稱是不言自明的,足以讓 DBA 理解其功能。

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