模拟多对多关系的正确方法

时间:2018-04-29 20:08:35

标签: mysql sql database database-design

我正在为个人项目建模数据库,我有以下疑问。 在以下选项之间建模我的数据库有什么区别?:

选项

enter image description here

B选项

enter image description here

选项 A B 之间的区别在于对合约表建模的方式,在 A选项 PK中合同的是针对所有属性组成的,但在 B选项中,合同的 PK 只是属性id_contract,但合同有两个不能的前缀键空。

我使用此设计的目标是允许用户和提供商之间签订多个合同,上述内容可以通过 A选项 B选项来实现,但是,如果我想到功能依赖关系,我需要 Id_user Id_Provider 数字序列来识别合同。问题是如果数字序列是自动增量的,它就成了代理键。暂且不谈数据库设计的所有理论,但如果这不是自我增长,它就成为实体身份不可或缺的一部分( Id_user Id_Provider 和< em>数字序列)。

我的问题是要知道选择模拟 A B 对数据库的良好设计进行建模的可能含义是什么。

非常感谢!

2 个答案:

答案 0 :(得分:1)

由于您无论如何都有唯一的代理键id_Contract,因此没有理由在Contract的主键中包含其他字段:单个主键就足够了。选项“B”也使程序员更容易看到您的意图。

通常,您不会在复合主键中包含单独的代理键属性。复合键的一大优点是能够在没有表的代理键的情况下使用。由于两种设计都允许用户和提供商之间签订多份合同,因此您没有避免使用代理密钥的清晰选项。

答案 1 :(得分:0)

这组索引

PRIMARY KEY(contract_id)
INDEX(user_id, provider_id, contract_id),
INDEX(provider_id, user_id, contract_id)

提供:

  • AUTO_INCREMENT需要的其余内容,即contract_id成为某些索引中的第一个列。
  • 从用户到所有提供商的有效方式,反之亦然(多对多表)。

这也有效:

PRIMARY KEY(user_id, provider_id, contract_id),
INDEX(provider_id, user_id, contract_id)
INDEX(contract_id)

注意:

  • 它不强制执行UNIQUEness contract_id,但如果您以正常方式使用AUTO_INCREMENT(从不INSERTing显式值),则不应该成为问题。
  • 它提供从每列开始的链接。

我不知道如何正确绘制模型。在某些时候,必须实现模式,并且 成为关于模式如何工作的真相来源。

实现InnoDB的方式,三个索引中的三个变为3个BTree,每个都包含所有列,但以不同的方式排列。也就是说,SELECTs应该找到三个相同的性能。 INSERTs会在&#39;末尾插入&#39;对于contract_id的BTree和在其他两个BTree的各个地方插入。再次,在性能上没有差异。

有关多对多表格的更多信息here