数据库设计 - 多对多或一对多 "Deal" 系统?
Database Design - Many to Many or One to Many "Deal" System?
我有一个用户可以相互 "Deal" 的系统,我想知道我应该使用哪种关系。
想像这样的系统。
我们有一个数据库,其中有两个 Table,一个 "Users" 和一个 "Deals"
'deal' table 中的每一行都与两个 'user' 行相关。
因此,当交易被创建时,一个用户是买家,一个用户是卖家。
我应该如何设计这个数据库?
我的意思是 table 的逻辑应该是什么?
一对一还是多对多?为什么?
https://i.stack.imgur.com/so7iS.jpg
Many-to-many 关系在这里不是一个选项,因为您需要保存额外的交易属性:价格、时间、对象。
因此,您可以在用户和交易之间使用 2 one-to-many 种关系。
您应该添加:
- SELLER_ID 和 BUYER_ID 字段到 Deals table.
- 从交易 table SELLER_ID 字段引用到用户 table 主键的外键。
- 从交易 table BUYER_ID 字段引用到用户 table 主键的外键。
嗯,有点像 1:many 和 many:many。
CREATE TABLE Deals (
seller_id SMALLINT UNSIGNED NOT NULL, -- link to `Users`
buyer_id SMALLINT UNSIGNED NOT NULL, -- link to `Users`
object_id SMALLINT UNSIGNED NOT NULL, -- link to `Objects`
price DECIMAL(8,2) NOT NULL,
etc.,
PRIMARY KEY(seller_id, buyer_id, object_id),
INDEX(...)
) ENGINE=InnoDB;
这允许两个 "users" 之间的多个对象销售,同一对象以不同的价格在其他人之间出售,等等
"Deal"是一个实体,只是"User"是一个实体。但是,由于一笔交易只涉及一个买家、卖家和对象,因此 deal:person 和 deal:object 的关系是 1:many。
另一方面,Deals
的行为类似于 many:many 关系 table,在某种意义上,卖家与买家、卖家与物品等相关
关于模式的一些细节:
- 您可能希望
seller_id
和 buyer_id
链接到单个 Users
table。 (除非买家和卖家之间存在足够的差异来证明不同的模式是合理的。)
- 我建议的架构中的 3 个 id 代表您的 jpg 中的彩色线条。也就是说,您几乎完成了架构!
SMALLINT UNSIGNED
(仅 2 个字节)允许 64K id。如果您认为这还不够,请选择更大的数据类型。
DECIMAL(8,2)
允许价格最高为 999999.99 美元、欧元等;如果这不符合您的货币需求,请更改。
Deals
中不需要 AUTO_INCREMENT PRIMARY KEY
。
- 根据需要添加更多
INDEXes
。
(已添加...)
如果相同 seller/buyer对可以sell/buy 相同 object_id, 那么PK(上图)不行。 (注意:PK 必须是 "unique"。)要解决此问题,您需要
deal_id INT UNSIGNED NOT NULL AUTO_INCREMENT,
PRIMARY KEY(deal_id),
INDEX(seller_id, buyer_id, object_id), -- in some order
INDEX(...)
在设计一组table时,我喜欢把重点放在需要收集在一起的东西上(例如,"deal"的属性)。并确保关系得到处理(例如,seller_id
)。通常事情会落入 "Entities"(交易、用户)和 "Relationships"(ids,当 1:many 时;单独映射 table 当 many:many 时)。在您的情况下,many:many 关系 table 本身就是一个实体。
我也想勾勒出 SELECTs
看看 table 是否方便地支持查询。
只有到了最后,才会想起FOREIGN KEYs
。通常,INDEXes
映射到 FK。
我很少使用 FK 或触发器 -- 我希望应用程序代码清楚地说明任何交易的所有步骤,包括 side-effects 否则将隐藏在 FK 和触发器中。
我有一个用户可以相互 "Deal" 的系统,我想知道我应该使用哪种关系。 想像这样的系统。 我们有一个数据库,其中有两个 Table,一个 "Users" 和一个 "Deals" 'deal' table 中的每一行都与两个 'user' 行相关。 因此,当交易被创建时,一个用户是买家,一个用户是卖家。 我应该如何设计这个数据库? 我的意思是 table 的逻辑应该是什么? 一对一还是多对多?为什么?
https://i.stack.imgur.com/so7iS.jpg
Many-to-many 关系在这里不是一个选项,因为您需要保存额外的交易属性:价格、时间、对象。
因此,您可以在用户和交易之间使用 2 one-to-many 种关系。
您应该添加:
- SELLER_ID 和 BUYER_ID 字段到 Deals table.
- 从交易 table SELLER_ID 字段引用到用户 table 主键的外键。
- 从交易 table BUYER_ID 字段引用到用户 table 主键的外键。
嗯,有点像 1:many 和 many:many。
CREATE TABLE Deals (
seller_id SMALLINT UNSIGNED NOT NULL, -- link to `Users`
buyer_id SMALLINT UNSIGNED NOT NULL, -- link to `Users`
object_id SMALLINT UNSIGNED NOT NULL, -- link to `Objects`
price DECIMAL(8,2) NOT NULL,
etc.,
PRIMARY KEY(seller_id, buyer_id, object_id),
INDEX(...)
) ENGINE=InnoDB;
这允许两个 "users" 之间的多个对象销售,同一对象以不同的价格在其他人之间出售,等等
"Deal"是一个实体,只是"User"是一个实体。但是,由于一笔交易只涉及一个买家、卖家和对象,因此 deal:person 和 deal:object 的关系是 1:many。
另一方面,Deals
的行为类似于 many:many 关系 table,在某种意义上,卖家与买家、卖家与物品等相关
关于模式的一些细节:
- 您可能希望
seller_id
和buyer_id
链接到单个Users
table。 (除非买家和卖家之间存在足够的差异来证明不同的模式是合理的。) - 我建议的架构中的 3 个 id 代表您的 jpg 中的彩色线条。也就是说,您几乎完成了架构!
SMALLINT UNSIGNED
(仅 2 个字节)允许 64K id。如果您认为这还不够,请选择更大的数据类型。DECIMAL(8,2)
允许价格最高为 999999.99 美元、欧元等;如果这不符合您的货币需求,请更改。Deals
中不需要AUTO_INCREMENT PRIMARY KEY
。- 根据需要添加更多
INDEXes
。
(已添加...)
如果相同 seller/buyer对可以sell/buy 相同 object_id, 那么PK(上图)不行。 (注意:PK 必须是 "unique"。)要解决此问题,您需要
deal_id INT UNSIGNED NOT NULL AUTO_INCREMENT,
PRIMARY KEY(deal_id),
INDEX(seller_id, buyer_id, object_id), -- in some order
INDEX(...)
在设计一组table时,我喜欢把重点放在需要收集在一起的东西上(例如,"deal"的属性)。并确保关系得到处理(例如,seller_id
)。通常事情会落入 "Entities"(交易、用户)和 "Relationships"(ids,当 1:many 时;单独映射 table 当 many:many 时)。在您的情况下,many:many 关系 table 本身就是一个实体。
我也想勾勒出 SELECTs
看看 table 是否方便地支持查询。
只有到了最后,才会想起FOREIGN KEYs
。通常,INDEXes
映射到 FK。
我很少使用 FK 或触发器 -- 我希望应用程序代码清楚地说明任何交易的所有步骤,包括 side-effects 否则将隐藏在 FK 和触发器中。