1

我面臨以下問題。有經驗的數據庫架構師的主題

我正在創建一個數據庫(說)人類的信息。所有的人類可以分爲三類:成年女性,成年男性,兒童。很明顯,諸如「高度」和「重量」的參數適用於所有類別。參數「兒童人數」僅適用於成年人,而參數「懷孕次數」僅適用於女性。另外,根據類別,每個參數可以被分類爲必需的或可選的(例如,對於成年人,參數「前伴侶的數量」是可選的)。

當我加載(說)「身高」和「體重」時,我檢查這兩個字段中的信息是否一致。也就是說,我把高度= 6'4''和重量= 10磅的記錄標記爲錯誤(顯然,這在物理上是不可能的)。我有幾個類似的驗證規則。

當我插入一個關於一個人的記錄,我需要反映信息的以下特點:

  1. 這個特定人的類別(包括所有的可選參數)最大可能的信息。
  2. 該類別所需的最小信息(例如,僅限於必填字段)
  3. 實際上爲這個特定人類插入的內容(即,無論這個人是否可以插入任何東西小於所需最小信息量或不小於)。這裏的非平凡問題是字段「XXX」可能具有NULL值,因爲我從來沒有在那裏插入任何內容,或者因爲我有意插入了完全空值。與具有默認值的字段相同的邏輯。所以應該反映出我已經處理了這個特定的領域。
  4. 什麼樣的插入信息已被驗證(即,即使我加載了5個字段,我可以檢查自我一致性只有3個字段,而忽略2左)。

所以我的問題是如何在技術上組織它。目前,所有這些所需的功能都是硬編碼的,沒有統一的邏輯或分成完全獨立的塊。我需要創建一個統一的方法。

我在這方面有一些天真的想法。例如,對於人類的每個類別,我可以創建並存儲可能字段的列表(我稱之爲「模板」)。 A可以標記這些必填字段。

當我插入關於人類的記錄時,我複製模板並標記來自此模板的字段實際上已被處理。在下一階段,我可以在模板的這個副本中標記那些目前將被驗證的字段。

驗證模塊通過以下方式進行了特別更正:對於每個驗證過程,我創建一個在此特定驗證過程中使用的字段列表。然後,我只會將那些實際上標記爲「待驗證」的字段的驗證過程稱爲待驗證特定人員的模板副本(請參閱前面的段落)。

正如你所看到的,這是解決這個問題最直接的方法。但我的猜測是,我還沒有意識到有很多相當標準化的方法。我真的懷疑我是世界上第一個解決這個問題的人。我不喜歡我的解決方案,因爲編寫代碼以正確反映此複製模板中記錄發生的所有「更新」是非常痛苦的。

所以,我請你分享你的意見,你會如何解決這個問題。

+0

@Nathan Hughes - 我希望在我實際完成這個項目的那一刻,所有12歲的孩子都會承擔更多的責任:)我正在研究的數據庫不是關於人類 - 而是關於金融工具。確實有很多這樣的「變性」股票和債券:)但我更願意用人類以這種簡單的方式來解釋自然。 – iCoffee 2013-03-26 18:15:58

+0

這不太適合SO。 SO適用於可以有明確「答案」的問題,而不是開放式的設計討論。 – Barmar 2013-03-26 18:23:05

+0

是的,我猜想它一定是一個奇怪的玩具的例子。它似乎確實對兩種情況都有數據驗證問題。 – 2013-03-26 18:46:45

回答

2

我覺得這裏有兩個問題:

  • 我怎麼存儲在數據庫中的多態性數據?
  • 如何驗證複雜的業務規則?

你應該分別解決它們 - 試圖一次性解決這兩個問題可能太難了。

有幾種RDBMSes中多態數據的方法 - 例如,ORM使用術語inheritance mapping。這裏的三個解決方案 - 每個類層次的表,每個子類的表和每個具體類的表 - 都是「純」的關係解決方案。您也可以使用「Entity-Attribute-Value」設計,或者使用文檔方法(以XML或JSON等結構化格式存儲數據) - 這些不是「純」關係選項,而是有其自己的位置。

通過使用rule engines來驗證複雜的商業規則 - 這些都是技術的超酷技術,但您必須確定您的問題與他們的解決方案非常相符 - 決定投資規則引擎意味着您的項目變爲規則引擎項目,而不是「人類」項目。或者,大多數主流解決方案都體現了應用程序業務邏輯層中實體的業務邏輯。這聽起來像你超出了這個。

+0

您對多態數據和商業方法的評論ruless是完美的!非常感謝!) – iCoffee 2013-03-26 20:39:14

0

我會用黨的角色模式(Silverston):

Party 
id 
name 

Individual : Party 
current_weight 
current_height 

PartyRole 
id 
party_id 
from_date 
to_date (nullable) 

AdultRole : PartyRole 
number_of_children 

FemaleAdultRole : AdultRole 
number_of_pregnancies 

Postgres有一個時間的延伸,從而使得你可以強制執行的一方只能同時播放一個角色(但仍保持自己的角色歷史) 。

使用表繼承。爲了簡化,使用單表繼承(具有空值),因爲沒有空值使用類表繼承。

1

這個確切的問題,無論是在健康方面還是在金融工具方面,都被用作Martin Fowlers書籍分析模式的主要例子。這是一個廣泛的話題。正如@NevilleK所說,你正試圖解決兩個問題,最好是單獨處理它們。解決這些問題的一個極簡化方法是:

1存儲多態數據 - 僅放置類別表中該類別通用的強制數據。對於可選數據,將這些數據放在與分類表1-1關係的單獨表中。只有存在要記錄的值時,纔在這些可選表格中輸入條目。數據驗證記錄也可以放在這些附加表格中。

2驗證複雜的業務規則 - 考慮可能出現的錯誤類型非常有用。有很多方法可以對錯誤進行分類,但是我發現最有用的方法是(a)輸入錯誤,只需查看數據即可知道錯誤值 - 例如1980-02-30。 (b)上下文錯誤,只能通過參考之前捕獲的日期來檢測錯誤 - 例如DoB 1995-03-15,結婚日期1996-08-26。和(c)在系統中 - 數據類型正確的地方;環境是好的;但只有當更多的信息曝光時,這些信息才能被檢測爲不正確,例如,如果我在1990-12-31註冊DoB,那麼它的情況有所不同。後一類錯誤通常必須通過正在開發的系統之外的程序來處理。

+0

我看到你真的面臨同樣的問題:)我完全同意你關於驗證的通過。對我而言,問題在於,在我的項目中,所有這些元素和功能都是硬編碼或混沌結構。我相信,現在是時候重新安排它) – iCoffee 2013-03-26 20:36:53