ER图中的基数
Cardinality in ER diagram
我做了一个项目,它本质上是一个网上书店,人们可以在那里买书和下订单。
我的数据库包含各种 table,例如:
user
user_shipping_address
user_payment_mode
user_order
order_shipping_address
order_billing_address
order_payment_details
我试图为此构建 EERD 图,但我对一件事感到困惑:user_order
只能有一个送货地址。我在 order_shipping_address
table 中创建了一个引用主键 order.id
的外键 order_id
。我在 table order
中也有一个 shipping_address_id
外键引用 order_shipping_address.id
。
当我尝试生成 ER 图时,它给了我两种不同的关系。 order
与送货地址之间存在 1:1 关系,送货地址与订单之间存在 1:M 关系。我不知道如何构建外键约束,因为我觉得订单 table 应该包含 shipping_address_id
并且送货地址应该包含 order_id
,对吗?这只会让一切变得更加混乱。
请帮我解决这个问题。
这是我的 EERD:
发生这种情况是因为您当前的设计意味着多个 user_order
行可以引用同一个 shipping_address
行。
您需要更改设计,以便多个 user_order
行不可能引用同一个 shipping_address
行。
至少有两种不同的可能解决方案:
- 在
user_order.shipping_address_id
上添加 UNIQUE
约束
- 或者:颠倒关系(这是我的首选,因为它消除了不需要的代理键):
- 删除
user_order.shipping_address_id
列。
- 将
shipping_address.id
更改为 shipping_address.order_id
,使其成为 user_order.id
的外键
- 使
shipping_address.order_id
成为 shipping_address
的新主键。
请注意,这两个选项都是非规范化的,因为它可以防止在不同订单之间共享送货地址(例如,如果同一客户多次重复订购相同的订单),尽管这可能是有意的 - 因此如果用户的未来地址更改不会无意中追溯更新旧订单运输记录。
其他一些提示:
- 考虑使用
int
而不是 bigint
作为您的标识 - 我怀疑您在每个 table. 中会有超过 20 亿行
- 不要盲目地对所有文本列使用
varchar(255)
- 使用它来对数据长度施加合理的限制,例如 state
不需要超过 2 个字符,如果你'重新存储缩写,同上 zipcode
如果您使用的是 ZIP+4,则可以是 varchar(10)
。
- 不要在您的数据库中存储完整的信用卡号!(如您的
payment
table 所示)- 这违反了 PCI 规则,在您的管辖范围内承担着巨大的责任,并且可能是非法疏忽。您的支付处理器将为您提供一个替代的不透明令牌值(或类似的东西)作为识别借记卡并将未来费用应用于存储的支付详细信息的一种方式 - 您可以合理存储的最多是最后 4 位数字。您是否加密数据在很大程度上是无关紧要的。
我做了一个项目,它本质上是一个网上书店,人们可以在那里买书和下订单。
我的数据库包含各种 table,例如:
user
user_shipping_address
user_payment_mode
user_order
order_shipping_address
order_billing_address
order_payment_details
我试图为此构建 EERD 图,但我对一件事感到困惑:user_order
只能有一个送货地址。我在 order_shipping_address
table 中创建了一个引用主键 order.id
的外键 order_id
。我在 table order
中也有一个 shipping_address_id
外键引用 order_shipping_address.id
。
当我尝试生成 ER 图时,它给了我两种不同的关系。 order
与送货地址之间存在 1:1 关系,送货地址与订单之间存在 1:M 关系。我不知道如何构建外键约束,因为我觉得订单 table 应该包含 shipping_address_id
并且送货地址应该包含 order_id
,对吗?这只会让一切变得更加混乱。
请帮我解决这个问题。
这是我的 EERD:
发生这种情况是因为您当前的设计意味着多个 user_order
行可以引用同一个 shipping_address
行。
您需要更改设计,以便多个 user_order
行不可能引用同一个 shipping_address
行。
至少有两种不同的可能解决方案:
- 在
user_order.shipping_address_id
上添加 - 或者:颠倒关系(这是我的首选,因为它消除了不需要的代理键):
- 删除
user_order.shipping_address_id
列。 - 将
shipping_address.id
更改为shipping_address.order_id
,使其成为user_order.id
的外键
- 使
shipping_address.order_id
成为shipping_address
的新主键。
- 删除
UNIQUE
约束
请注意,这两个选项都是非规范化的,因为它可以防止在不同订单之间共享送货地址(例如,如果同一客户多次重复订购相同的订单),尽管这可能是有意的 - 因此如果用户的未来地址更改不会无意中追溯更新旧订单运输记录。
其他一些提示:
- 考虑使用
int
而不是bigint
作为您的标识 - 我怀疑您在每个 table. 中会有超过 20 亿行
- 不要盲目地对所有文本列使用
varchar(255)
- 使用它来对数据长度施加合理的限制,例如state
不需要超过 2 个字符,如果你'重新存储缩写,同上zipcode
如果您使用的是 ZIP+4,则可以是varchar(10)
。 - 不要在您的数据库中存储完整的信用卡号!(如您的
payment
table 所示)- 这违反了 PCI 规则,在您的管辖范围内承担着巨大的责任,并且可能是非法疏忽。您的支付处理器将为您提供一个替代的不透明令牌值(或类似的东西)作为识别借记卡并将未来费用应用于存储的支付详细信息的一种方式 - 您可以合理存储的最多是最后 4 位数字。您是否加密数据在很大程度上是无关紧要的。