2008-11-20 75 views
24

我想知道這是不是一個好的設計。我有許多需要地址信息的表格(例如街道,郵政編碼/郵編,國家,傳真,電子郵件)。有時相同的地址會重複多次。例如,可以針對供應商存儲地址,然後將每個採購訂單發送給他們。然後供應商可以更改他們的地址,任何後續的採購訂單都應該有新的地址。這比這更復雜,但這是一個示例要求。這是在關係數據庫中建模地址信息的好方法嗎?

選項1 將所有地址列作爲屬性放在各個表上。在供應商創建時將詳細信息從供應商複製到採購訂單。可能存儲多個副本的

選項2 創建單獨的地址表。從供應商和採購訂單表中獲取一個外鍵到地址表。只允許在地址表上插入和刪除,因爲更新可能會改變超出您的預期。然後我會有一些計劃的任務,從地址表中刪除任何不再被任何東西引用的行,這樣就可以不使用未使用的行。也許在地址表中的所有非pk列上也有一個唯一的約束來阻止重複。

我傾向於選項2.是否有更好的方法?

編輯:我必須保留購買訂單上的地址,因爲它發送時。另外,我建議可能有一個交付地址和一個帳單地址(還有一堆其他地址信息表),這有點複雜。

過了一段時間,我會根​​據日期大小地刪除舊的採購訂單。在此之後,我打算收集任何不被任何東西引用的地址記錄(否則感覺就像我正在創建一個泄漏)。

回答

24

我實際上將其作爲我的一個面試問題使用。以下是一個良好的開端:

Addresses 
--------- 
AddressId (PK) 
Street1 
... (etc) 

AddressTypes 
------------ 
AddressTypeId 
AddressTypeName 

UserAddresses (substitute "Company", "Account", whatever for Users) 
------------- 
UserId 
AddressTypeId 
AddressId 

這樣,你的地址是完全不知道如何使用它們,和你的實體(用戶,帳戶)也不直接瞭解地址。這完全取決於你創建的鏈接表(在這種情況下UserAddresses,但你可以做任何適合你的模型)。

對於一個潛在的大型數據庫,一個有點矛盾的建議:繼續,並將一個「主」地址直接放在您的實體(在這種情況下在Users表中)以及一個「HasMoreAddresses」字段。與僅僅使用上面的乾淨設計相比,它看起來很瑣碎,但可以簡化對典型用例的編碼,反規範化可以對性能產生很大的影響。

1

您是否想要保留採購訂單最初地址的歷史記錄?

如果是,請使用選項1,否則將其存儲在供應商表中並將每個採購訂單鏈接到供應商。

順便說一句:糟糕的數據庫設計的一個明確標誌是需要一個自動化的工作來保持數據「清理」或同步。選項2很可能不是這個方法的主意

+0

雖然我同意需要一個cron作業來清理您的數據是一個非常糟糕的跡象,選項2是正確的方式來做到這一點。選項2是標準化的解決方案。正如cagcowboy所說,實際上並不需要一個cron工作。 – rmeador 2008-11-20 22:51:02

+0

在我看來,這是過度規範化,會創造更多的頭痛,而不是價值。只要地址描述了添加到表中的實體,只要它們沒有被過度複製,選項1就沒有問題。 – JohnFx 2008-11-21 15:39:26

1

爲什麼地址表上的任何行都會被忽略?當然,他們仍然會在使用它們的採購訂單中指出?

在我看來,停止重複應該是優先事項,從而否定任何清理的需要。

+0

最終,我將刪除舊採購訂單,因此某個地址可能不再使用任何地址。 – 2008-11-20 22:43:52

+0

如果地址引用都是外鍵(因此任何引用地址表的表都有一個正式的外鍵),那麼刪除觸發器或update-of-address-id觸發器可以嘗試刪除舊地址標識地址表。如果成功,則沒有參考文獻。 – 2008-11-20 22:51:59

+0

繼續:如果觸發的刪除失敗,則意味着另一行仍然引用地址行(可能還有其他錯誤),並且只要DBMS不會阻止您忽略該錯誤(它不應該),那麼你可以繼續引用刪除或更新。 – 2008-11-20 22:56:42

3

我想我JohnFx同意..

約(snail-)郵件地址,因爲您要包括國家,我想你想船國際/郵件,請保留地址字段大多是自由的文本另一件事。當挪威沒有郵政編碼時,我們有5位數的郵政編碼,我們有4位數的郵政編號。

最好的領域是:

  • 名稱/公司
  • 地址(多行文本域)
  • 國家

這應該是非常全球性的,如果美國郵政系統要求以特定格式郵政編碼,然後將其包括在內,但除非美國被選爲國家,否則將其作爲可選項。每個人都知道如何格式化在他們國家的地址,所以只要你保持線路分明,它應該是好的...

6

選項2,毫無疑問。

需要注意的一些重要事項:設計中的一個重要方面是向用戶指出地址彼此鏈接。即公司地址與送貨地址相同;如果他們想要更改送貨地址,他們是否也想更改公司地址,或者他們是否想要指定新的裝貨碼頭?這種東西,以及向用戶呈現這些信息並用這種粒度改變事物的能力是非常重要的。這一點對於更新也很重要;爲用戶提供「分割」條目的粒度。不是說這種UI很容易設計;事實上,這是一個婊子。但是做這件事真的很重要。幾乎肯定會導致用戶感到非常沮喪和煩惱。

另外;我強烈建議保留舊地址數據;不要運行一個進程來清理它。除非你有一個非常繁忙的數據庫,否則你的數據庫軟件將能夠處理多餘的數據。真。我看到有關數據庫的一個常見錯誤是企圖過度優化;你想優化你的查詢,但你不想優化你的未使用的數據。 (同樣,如果你的數據庫活動是非常高的,你可能需要做些什麼,但是幾乎可以肯定的是你的數據庫能夠很好地工作,在表中仍然有大量數據。)在大多數情況下,它實際上更有優勢簡單地讓數據庫增長,而不是試圖優化它。 (從您的表中刪除偶發性數據不會導致數據庫大小的顯着減少,並且當它的確如此時,引起的重新索引可能會造成數據庫巨大的損失。)

0

在訂單的情況下,如果訂單已發送,您將永遠不想更新地址,因爲人員(或公司)地址已更改。如果訂單出現問題,您就會記下訂單實際發送的位置。

地址表是一個好主意。對它做一個唯一的約束,以便同一個實體不能有重複的地址。你仍然可以得到它們,因爲用戶可能會添加另一個,而不是查看它們,如果它們稍微有點不同(St.而不是Street),那麼唯一約束不會阻止它。將訂單創建時的數據複製到訂單。這是您需要多條記錄的一種情況,因爲您需要有關您發送的內容的歷史記錄。只允許插入和刪除表格對我來說沒有任何意義,因爲它們比更新更安全,並且涉及數據庫的更多工作。一次調用數據庫即可完成更新。如果地址在您的想法中發生變化,那麼您必須先刪除舊地址,然後插入新地址。不僅有更多的數據庫調用,而且有兩次發生代碼錯誤的機會。

0

我見過使用選項1的每個系統都會遇到數據質量問題。 5年後,所有地址中的30%將不再是最新的。

相關問題