0

我需要将Shipping address,Shipping postcode和放入一张表中Billing AddressBilling PostcodeCustomer

这违反了 3NF 吗?

4

2 回答 2

1

这违反了 3NF 吗?

非常严格地说:是的。

实际上:没有。

如果您计划:

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

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

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


考虑“实用”

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

与“完全标准化”

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

此外,后一种系统让您在理论上能够为每个客户拥有多个送货地址。

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

于 2012-11-08T14:02:49.170 回答
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     |
....

现在您可以通过 join 获取地址

于 2012-11-08T14:04:19.527 回答