2011-10-26 157 views
20

我應該實現讀取數據庫規範化(使用連接表)還是應該將ENUM類型用於靜態或動態數據?MySQL數據庫規範化

例如:

我有一個表USERuser_status。我應該創建一個表格status嗎?或者我創建一個包含狀態的ENUM列表?

謝謝G

回答

25

恕我直言,枚舉延長使得它更容易嵌入語義到表中,並通過提高效率:

  1. 減少的聯接需要查詢
  2. 減少打開的表的數目數在DBMS

我所知道的唯一的缺點是

  1. 對E NUM類型不受其他DBMS
  2. 如果你選擇的附加價值在日後添加到ENUM集,你申請一個DDL更新實現的 - 這可能需要很長的時間,一個非常大的表

HTH

C.

+1

性能測試:http://www.mysqlperformanceblog.com/2008/01/24/enum-fields-vs-varchar-vs-int-joined-table-what-is-faster/ –

+1

還有其他問題'ENUM '。首先,所有的'ENUM'列都可以取一個空字符串的特殊「未知」值(如果允許的話,除了'NULL'外)。此外,除非使用嚴格的SQL模式,否則此值將用於任何無效值的賦值。這可能會導致意外的數據庫不一致;另外,如果在ENUM列表中實際上有一個明確的空字符串值,這可能會導致巨大的混淆(因爲必須檢查數值以確定存儲哪個「類型」空字符串)。 – eggyal

+1

此外,在數值上下文中隱式轉換爲數值可能會導致相當大的混淆 - 特別是如果試圖將代表數字的字符串用作ENUM值。該手冊給出了一個'ENUM'列表的好例子('0','1','2')':「*如果存儲了'2',它將被解釋爲一個索引值,並且變成''1 ''(索引爲2的值),如果存儲「2」,則與枚舉值相匹配,因此存儲爲「2」;如果存儲「3」,則不匹配枚舉值,所以它被當作一個索引並且變成''2'(索引爲3的值)。*「 – eggyal

0

它取決於體系結構和許多其他因素。

例如,除了使用存儲過程外,您不允許讀取/寫入數據。在這種情況下,你可以自由使用「tinyint」數據類型。如果允許使用直接查詢進行讀/寫,最好使用約束條件,即ENUM來避免不正確的狀態(如果UI或後端可以將此「錯誤」狀態當然)。

另一方面(也有可能)數據流量可能會發生變化,您可能需要添加新的狀態。在這種情況下,您需要: 1)如果您有靜態數據類型,則不執行任何操作; 2)如果您有ENUM,請改變。

所以...我的回答是:這取決於您的應用程序和您的要求。

+2

您可以通過強制執行,以及外鍵約束正確的狀態(使用InnoDB表。) – Inca

+0

...,然後再創建一個表。我認爲「過度規範化」(每個狀態都有一個額外的表格)通常不是一個好方法。 – ravnur

+0

你能解釋爲什麼不呢?有很多桌子是沒有問題的。 (並且它們允許額外的靈活性,例如向狀態添加可編輯的描述,或者在保留舊記錄的同時禁用新記錄。) – Inca

1

要考慮的其他的東西......

枚舉只能通數據庫結構的修改更新別處鏈接表允許動態創建的記錄。