这会违反3NF吗?

时间:2012-11-08 13:50:34

标签: database normalization

我需要将Shipping addressShipping postcodeBilling AddressBilling Postcode放入一个Customer表格。

这是否违反了3NF?

2 个答案:

答案 0 :(得分:1)

  

这是否违反了3NF?

非常严格来说:是的。

实际上说:不。

如果您计划:

  • 在您的数据库中拥有专用的“地址”实体(即:当地址只是附加到客户记录的自由文本时)
  • 每个客户拥有可变数量的地址(但只有两个)
  • 必须为您要选择的每个地址写一个LEFT JOIN ...

......然后坚持你的设计。

将地址规范化为单独的表与将名字和姓氏标准化为单独的表一样明智,因为它们往往会重复。不要这样做。


考虑“实用”

SELECT
  CustomerId
  CustomerName,
  COALESCE(BillingAddress, ShippingAddress) AS BillingAddress,
  COALESCE(BillingPostcode, ShippingPostcode) AS BillingPostcode
FROM
  Customer

VS。 “完全正常化”

SELECT
  c.CustomerId
  c.CustomerName,
  COALESCE(bill.Address, ship.Address) AS BillingAddress,
  COALESCE(bill.Postcode, ship.Postcode) AS BillingPostcode
FROM
  Customer AS c
  -- join customer-to-address-resolution for billing
  LEFT JOIN CustomerAddress AS custAddrB ON custAddrB.CustomerId = c.CustomerId
                                            AND custAddrB.AddressType = "Billing"
  LEFT JOIN Address         AS      bill ON bill.AddressId = custAddrB.AddressId
  -- join customer-to-address-resolution for shipping
  LEFT JOIN CustomerAddress AS custAddrS ON custAddrS.CustomerId = c.CustomerId
                                            AND custAddrS.AddressType = "Shipping"
  LEFT JOIN Address         AS      ship ON ship.AddressId = custAddrS.AddressId

另外,后一种系统为您提供了每个客户拥有多个送货地址的头痛理论能力。

后一种系统的最大好处是:如果他们改变了街道的名称,你需要做的就是更新一条记录。换句话说:没有任何好处。

答案 1 :(得分:1)

是的,因为您将使用这些地址创建冗余,或者您需要在数据库中具有NULL值(例如,当运送和计费地址相同时),3NF禁止这些值。更好地使用这样的东西:

table customer
... | ... | shipping_address_id | billing_address_id |
----+-----+---------------------+--------------------+
 x  |  y  | 23                  | 24                 |
 x  |  y  | 25                  | 25                 |
...

table address
id | address | postcode | city | country |
---+---------+----------+------+---------+
23 | aaaa    | 1234     | foo  | bar     |
24 | sdfsd   | 2345     | sdf  | sdf     |
....

现在您可以通过加入

获取地址