我需要将Shipping address
,Shipping postcode
和放入一张表中Billing Address
。Billing Postcode
Customer
这违反了 3NF 吗?
我需要将Shipping address
,Shipping postcode
和放入一张表中Billing Address
。Billing Postcode
Customer
这违反了 3NF 吗?
这违反了 3NF 吗?
非常严格地说:是的。
实际上:没有。
如果您不计划:
...然后坚持你的设计。
将地址规范化到单独的表中与将名字和姓氏规范化到单独的表中一样明智,因为它们往往会重复。不要这样做。
考虑“实用”
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
此外,后一种系统让您在理论上能够为每个客户拥有多个送货地址。
后一种系统的最大好处是:如果他们改变了街道的名称,您需要做的就是更新一条记录。换句话说:没有任何好处。
是的,因为您将使用这些地址创建冗余,或者您需要在数据库中有 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 获取地址