2010-01-07 55 views
5

我有如下表:與外鍵約束相關的表使用空值的

Cateogories

  • 類別ID(int)的主鍵
  • 類別名稱(VARCHAR)

項目

  • ITE MID(INT)主鍵
  • 類別ID(INT)
  • ITEMNAME(VARCHAR)

有上Items.CategoryID外鍵約束。有一種可能性,即在創建新項目時不會分配類別。

將Items.CategoryID設置爲允許空值並處理我的代碼中的空值或者最好不允許空值,將默認的CategoryID設置爲1並在Categories表中創建一個名爲「Uncategorized」的虛擬記錄,然後在我的代碼中處理這個虛擬類別?

+0

我原本應該發佈一個項目只能在一個類別中。 – jpshook 2010-01-07 14:47:36

+0

相關:http://stackoverflow.com/questions/2016730/column-nullability-optionality-null-vs-not-null – 2010-01-08 02:51:25

回答

6

邏輯上正確的方法是對CategoryID列是NULL當沒有該項目類別。

如果獲得任何與使用NULL相關的陷阱被困,那麼最有可能的是,設計處理不當所採取的事實,項目不能有一類帳戶的跡象。修復設計。 NULL將確保您堅持解決正確的問題。

+0

即使該類別爲「雜項」或類似,此上下文中的項目也將始終具有類別。只有當字段具有無數據狀態的邏輯可能性時才應使用NULL,例如一個還活着的人的死亡日期。 – melkisadek 2010-01-07 14:10:15

+1

海報說有時候某個物品沒有分類。這與其他雜項或其他虛擬類別不同。 你有一些我不知道的信息嗎? – 2010-01-07 14:20:28

+1

另一個允許NULL無類別的理由 - 如果您有下拉列表的類別,那麼用戶將最終看到這個虛擬類別,除非您硬編碼從下拉列表中排除它,無論如何需要特殊編碼。 – 2010-01-07 14:30:03

0

SQL NULLs are tricky,所以我覺得你是一個類別定點更好。

+0

幾乎列表中的每個項目符號都很容易在數學上解釋和/或**是**解釋在SQL規範中。這是一個回答問題的網站,不會發布關於標準規格如何不按照您認爲應該的方式工作的抱怨。 – Aaronaught 2010-01-07 14:34:36

+0

我不需要抱怨標準 - 總體上非常有用的標準 - 但公平地說,應該避免它的某些部分。 「易於數學解釋」,這部分不是。 – Tobu 2010-01-07 15:01:44

+1

NULL ANSI規範不一致,通常被認爲是中斷的。大多數認爲他們理解NULL的開發人員確實沒有。 – KenFar 2010-01-07 20:42:40

0

在這種情況下,我認爲這確實是個人偏好的問題。無論哪種方式,你都必須處理代碼中未分類的項目。

1

理想情況下,你會希望允許創建一個項目之前,迫使一個類別的選擇。如果一個項目將來沒有任何類別,那麼您需要專門創建一個類別來處理這個類別。我個人不會稱之爲「未分類」,因爲這意味着用戶可以稍後追趕它 - 他們會忘記做出驚人的規律!

尋求邏輯一致性,否則你最終會陷入混亂。如果這意味着創建一個「雜項」類別,那麼做到這一點,並確保(a)用戶知道何時使用它和(b)定期報告以確保項目正確分類。

2

這取決於:

如果您的項目真的沒有類別,然後我會允許NULL S,因爲這是你擁有的一切:沒有類別編號。

如果要列出所有類別,你不希望顯示的虛擬行,所以你必須忽略。

如果要顯示所有項目並顯示類別,最好注意有沒有類別的項目,所以在這種情況下您將使用LEFT JOIN

如果可能,請在實際保存項目之前更改您的應用程序以選擇一個類別。


如果你想治療是Uncategorized類別就像其他類別(與其他類別一一列舉了,算分配給它的項目,在列表/下拉列表中選擇它),那麼它應該得到它自己的類別, Item.CategoryId應該是NOT NULL

0

我不相信任何一種選擇都很好。

如果您選擇NULL方法,您將遇到涉及使用NULL的陷阱問題。如果您選擇不允許使用空值,則需要處理如果您刪除項目將級聯的類別的情況。

IMO最好的設計是有三張桌子。

Categories 
ID 
Name 

Items 
ID 
Name 

Categories2Items 
CategoryID 
ItemID 

這消除了對NULL的需求(以及所涉及的陷阱),它屬於幾個類別,以及可以讓你有未分類的項目,項目。這種設計也是Boyce-Codd Normal形式,總是一件好事.. en.wikipedia.org/wiki/BCNF

+1

然後你得到每個項目的多個類別,稱他們的標籤。這是一個很好的設計,但是OP想要什麼? – Tobu 2010-01-07 14:23:40

+0

我應該提到,在這種情況下,它是一對一的物品類別。您的答案適用於多方面的情況。對於一對一,這會使SQL複雜化,並要求您在應用程序中強制執行一對一(凌亂)。我原來的設計至少有效3NF。 – jpshook 2010-01-07 14:45:58

+0

是的,我知道。但設計是可擴展的,並消除了兩種設計中的許多問題。此外,如果我可能是一個挑逗,類別不是每個定義不相交。 但是,如果這不是OP想要的,那麼選擇NULL方法顯然比擁有一個哨兵類別更好。刪除某個項目所屬的類別將要求CASCADE刪除該項目,這可能不是一件好事,會觸發並非所有DBMS都支持或者將類別ID保留爲空值。然後,OP將在其數據庫中包含NULL分類和未分類項目。 – 2010-01-07 14:53:24

1

對於這種類型的簡單查找表,幾乎總是禁止NULL並在查找表中有未知值。

爲什麼?

  • 由於ANSI NULL規範不一致且非常複雜。處理空值大大增加了編碼缺陷的可能性,並且需要更多的代碼來編寫
  • 由於很少開發人員真正瞭解NULL在所有場景中的工作原理
  • 因爲它簡化了您的模型並且很好地查詢。使用非常簡單的sql,您可以將任何方向的內部連接很好地結合在一起。

然而,一些注意事項:

  • 您可能需要不止一個「虛擬」的價值更多:一爲「未知」,另一個是「未分配」。當然,NULL綁定到一個單一的值,所以如果你這樣做,你會超出最低標準超過&。
  • 您最終有時會得到額外的非關鍵屬性,這些關鍵屬性必須是可以爲空或者對於虛擬行攜帶'n/a'類型值。對於嚴重非規格化的查找表(如倉儲維度),您可能希望空值允許使用這些列,因爲'n/a'不適用於時間戳,金額等。
  • 如果您將此技術應用於更多簡單的查找表會大大地讓你的設計複雜化。不要這樣做。