2008-11-22 102 views
12

在我的應用程序中,我有一個Customer類和一個Address類。類有Address類的三個實例:customerAddress,deliveryAddressinvoiceAddress一個表格或單獨表格中的三個客戶地址?

什麼是在數據庫中反映這種結構的最佳方式?

  • 直接的方法是客戶表和單獨的地址表。
  • 更非規範化的方式將只是一個客戶表格,表格中的每個地址欄(示例「街頭」:customer_street,delivery_street,invoice_street)

什麼是與您的經驗?這些方法有什麼優點和缺點嗎?

+0

請參閱http://stackoverflow.com/questions/648463/best-way-to-model-customer-address/2995299#2995299 – 2010-06-08 06:59:59

回答

11

如果你是100%肯定,客戶將永遠只能有你所描述的3個地址,那麼這是確定:

CREATE TABLE Customer 
(
    ID int not null IDENTITY(1,1) PRIMARY KEY, 
    Name varchar(60) not null, 
    customerAddress int not null 
     CONSTRAINT FK_Address1_AddressID FOREIGN KEY References Address(ID), 
    deliveryAddress int null 
      CONSTRAINT FK_Address2_AddressID FOREIGN KEY References Address(ID), 
    invoiceAddress int null 
      CONSTRAINT FK_Address3_AddressID FOREIGN KEY References Address(ID), 
    -- etc 
) 

CREATE TABLE Address 
(
    ID int not null IDENTITY(1,1) PRIMARY KEY, 
    Street varchar(120) not null 
    -- etc 
) 

否則我將模型是這樣的:

CREATE TABLE Customer 
(
    ID int not null IDENTITY(1,1) PRIMARY KEY, 
    Name varchar(60) not null 
    -- etc 
) 

CREATE TABLE Address 
(
    ID int not null IDENTITY(1,1) PRIMARY KEY, 
    CustomerID int not null 
     CONSTRAINT FK_Customer_CustomerID FOREIGN KEY References Customer(ID), 
    Street varchar(120) not null, 
    AddressType int not null 
    -- etc 
) 
5

我會去(如數據庫理論教)兩個單獨的表:客戶和地址。

如您所說,將三個字段放在Customer表中的想法很糟糕,因爲這會違反規範化規則(並且在地址超過三個時失敗)。

編輯:另外,我會分幾個字段中的地址表記錄,一個用於toponomastic前綴,一個用於街道等,並在這些字段上放置一個唯一鍵。否則,你會結束數據庫的重複。

+1

將3地址ID列放在Customer表中不會破壞任何規範化規則。 – 2008-11-22 08:35:39

+0

OP正在討論在客戶表中放置三個*地址*,而不是三個ID。 – 2008-11-22 08:39:00

+2

不能記住所有5級標準化,但客戶表中的三個地址字段意味着(1)數據庫中浪費的空間和(2)三個地址的限制。一個單獨的地址表可以消除這兩個問題。 – paxdiablo 2008-11-22 08:40:29

4

我會去與非規範化。這很容易。

如果您規範化它,地址表將要求您刪除重複項並重新鏈接客戶表中的記錄。如果我擁有相同的送貨地址和發票地址,它似乎應鏈接到相同的記錄。如果我換一個,你需要:

  1. 創建一個新的地址記錄。
  2. 重新鏈接客戶記錄。

如果我改回來,你需要檢查:

  1. 做類似的地址條目已經存在。
  2. 重新鏈接客戶記錄。

這種編程開銷似乎可以避免規範化似乎可以提供的更少空間的優勢。正如您所指出的,非規範化解決方案將提供更快的查詢和更容易的維護(編程方式)。這似乎是我的決定性因素。

正如上面指出的,規範化的解決方案將允許您稍後添加更多地址。但是,無論如何,您必須爲外鍵添加一個字段,除非您計劃在沒有從客戶到地址表的鏈接的情況下組織表。

優勢歸

  • 空間較小。
  • 重複的邏輯還挺建(雖然也許他們不實際上重複?)
  • 支持增加新的地址域(有點)的。

優勢規格化

  • 更快的查詢。
  • 編程少。
1

我的兩分錢是,如果你有一個令人信服的理由,那麼你描述的方式是非標準化的好的。有時候,這個原因可能像高度自信一樣簡單,你永遠不需要規範化的形式。正如Stefan Mai所暗示的那樣,如果您只需要使用您指定的三種地址類型,那麼只需檢索並更新單個表格就容易多了。另一方面,如果三個地址的要​​求有可能改變,那麼它可能會,並且提前是正常化的最佳時間。

4

與2表,客戶,地址。

一旦地址已在地址表中創建通常不會允許它們進行修改(也許是一個特定的工具來糾正拼寫錯誤)。 IOW使用地址本身創建地址idempotent的ID。

您現在可以在任何地方引用這些地址表條目。例如,當訂單派發給客戶時,訂單表引用的地址ID可以與客戶表中的DeliveryAddressID字段中的地址ID相同。

如果客戶希望對文件的送貨地址更改當前到一個新的,創建一個新的地址記錄。歷史交付數據不受此影響,但新訂單自動使用新地址。

注緩存編輯部地址對象(它們是不變的,是長期的緩存安全)時,這也是有幫助的,他們可以分發和平等更容易測試(通過ID屬性)。

2

我有這樣的禪車(也可能是自從爲好),在訂單表,不知道爲什麼他們那裏去,甚至更多,因爲他們有一個地址表。
我看到的唯一有效的理由是爲了記錄目的:即使客戶更改他們的地址,訂單信息也不能改變,它反映訂單時的數據。現在

,實在是有點浪費,如果更同客戶做大量的訂單。一個可能的解決方案是保留地址的歷史記錄並將它們與訂單進行對照。
我不知道這些不可變的地址(或者如果他們沒有相關的訂單,是可變的)應該保存在常規的地址簿或者單獨的歷史記錄表中,只有在訂單完成時才填寫(避免重複,如果同一個客戶當然保持相同的地址)。
前者的優點是避免擁有兩張非常相似的結構和重複信息的表格,但隨着歷史的發展可能會妨礙表演(?)。儘管人們在實踐中很少改變這些信息。
後者具有分離角色的優點(一個是不可改變的,而另一個是不可改變的),歷史很少使用。總體而言,如果您的應用程序不需要保留歷史記錄,那麼只需使用兩個分開的表格即可。

2

在這種情況下,將每個地址字段放在不同的行中不是標準化。這只是表分區。任何具有更多表的模式都是「更規範化」的假設是錯誤的。

比方說,我們在數據庫中這兩種可選模式: 1)用戶:user_ID的,用戶名,密碼

2)用戶:USER_ID,password_id 密碼:password_id,密碼

是(2 )比(1)更「正常化」?

在這個OP的情況下,只要: 1)我們將該地址視爲一個原子值, 2)應用程序只需要這三種類型的地址。

然後,將每個地址存儲在不同的列中同樣有效。第二個解決方案不會將地址分解爲其組件(國家,城鎮,街道等)。因此它不是比第一個更「標準化」!

相關問題