2010-04-26 97 views
4

我正在設計一個產品數據庫,其中根據產品的類型,產品可能具有非常不同的屬性,但屬性對於每種類型都是固定的,類型根本不可管理。例如:數據庫設計:具有不同屬性的對象

雜誌:標題,ISSUE_NUMBER,頁數,份數,close_date,RELEASE_DATE
WEB_SITE:名,帶寬,命中,date_from,DATE_TO

我想使用InnoDB和執行數據庫完整性就像引擎允許的一樣。推薦的方法是什麼?

我討厭那些表有100列,大部分的數值是NULL,所以我想過這樣的事情設計:

product_type 
============ 

product_type_id INT 
product_type_name VARCHAR 

product 
======= 

product_id INT 
product_name VARCHAR 
product_type_id INT -> Foreign key to product_type.product_type_id 
valid_since DATETIME 
valid_to DATETIME 

magazine 
======== 

magazine_id INT 
title VARCHAR 
product_id INT -> Foreign key to product.product_id 
issue_number INT 
pages INT 
copies INT 
close_date DATETIME 
release_date DATETIME 

web_site 
======== 

web_site_id INT 
name VARCHAR 
product_id INT -> Foreign key to product.product_id 
bandwidth INT 
hits INT 
date_from DATETIME 
date_to DATETIME 

這可處理級聯刪除產品,但...好吧,我不完全相信......

回答

5

這是關係表阻抗不匹配的經典OO設計。您所描述的表格設計被稱爲「每個子類的表格」。最常見的三種設計都妥協相比,你的對象實際上看起來就像在你的應用程序:

每子

設計

  • 表具體類每一個分層
    1. 表你不喜歡 - 「表中有100列,大多數值爲NULL」 - 是2.一個表來存儲整個專業化層次結構。由於各種原因,這是最不靈活的,包括 - 如果您的應用需要新的子類,則需要添加列。您描述的設計容易變得更好,因爲您可以通過添加由product_type中的值描述的新子類表來添加擴展。

      其餘選項 - 1.每個具體類的表 - 通常是不合需要的,因爲在每個專業化表中實現所有公共字段需要重複。雖然,優點是你不需要執行任何連接,並且子類表甚至可以在非常大的系統中的不同db實例上。

      你描述的設計是完全可行的。下面的變化是如果您使用ORM工具來執行您的CRUD操作,它可能看起來如何。請注意,每個子類表中的ID是層次結構中父表的FK值。一個好的ORM將根據product.id和product.product_type_id中的鑑別值的值自動管理正確的子類表CRUD。無論您是否計劃使用ORM,只要查看他們所做的設計決策,就可以查看hibernate加入的子類文檔。

      product 
      ======= 
      
      id INT 
      product_name VARCHAR 
      product_type_id INT -> Foreign key to product_type.product_type_id 
      valid_since DATETIME 
      valid_to DATETIME 
      
      magazine 
      ======== 
      
      id INT -> Foreign key to product.product_id 
      title VARCHAR 
      .. 
      
      web_site 
      ======== 
      
      id INT -> Foreign key to product.product_id INT 
      name VARCHAR 
      .. 
      
  • +0

    三種可能的設計的好概述,謝謝。 所有的答案都很好,但我只能選一個'<:-)' – 2010-04-27 11:30:26

    2

    除了您可能需要考慮「產品」和通常稱爲「庫存單位」(SKU)之間的區別之外,您似乎大致走上了正軌。是一個25單位的盒子(某種特定種類的)回形針與50單位的盒子是相同的「產品」嗎?就商店或任何類型的庫存系統而言,區分很重要;在某些情況下,確實在包裝中有一個簡單的區別,否則相同數量的相同底層「產品」可能會給您不同的SKU來跟蹤。

    您需要決定在哪個位置跟蹤此問題,如果它對您的應用程序很重要(可能會確定您的產品佈局,並且在其他表格中處理SKU目的的打包問題,例如,即使對於某些應用程序而言,這可能會帶來一些小的開銷)。

    1

    這實際上是一種在傳統RDBMS中「執行」某種OO設計的標準方法。

    所有「通用」屬性都放在主表上(例如Price,如果它在產品表級別進行維護,可能很容易成爲主表的一部分),而具體則放在子表上。

    理論上,如果你有子子類型(例如雜誌可能在日報和4色期刊中可能是子類型的,也許是期刊有保質期的時間間隔),你也可以添加一個或多個子類型...

    這是很常見的(並證明)設計。唯一值得關注的是主表總是會與大多數操作的至少一個子表結合在一起。如果你有數以萬計的項目,這可能會有性能影響。

    另一方面,像刪除一個項目(我建議邏輯刪除,在主表上設置一個標誌爲「真」)的常見操作將爲每種類型的子類型執行一次。

    無論如何,去吧。也許谷歌「面向RDBMS映射的面向對象」或某些爲a complete discussion

    相關問題