mysql - 多对多表 id 的最佳实践
问题描述
我对多对多表 id(主键)有一些疑问。根据 Laravel 文档,多对多关系由两个模型和三个表组成。每个模型都有对应的表,中间表有 as 字段:
- 自动增量 ID
- table1_id
- table2_id
- 其他属性 ...
到目前为止,一切都很好。我已经用过很多次了,使用助手“pivot”访问字段,并使用“updateExistingPivot”等更新这些字段。
我的问题是是否值得从其他表的属性中利用中间表的 ID,例如 FK。
例子:
在我的应用程序中,我有这些模型:
- 机器
- 产品
- 限制
这四个表:
- 机器(id,名称,...)[机器]
- 产品(id,名称,...)[产品]
- machine_products (id, machine_id[FK], product_id[FK], price) [无型号]
- 限制 (id, machine_product_id[FK], day, begin_hour, end_hour) [限制]
给定特定的机器和产品,有 N 个限制。一种限制属于一种特定的机器和产品。
如您所见,我利用自动增量 ID(中间表的主键)来关联限制。但是这样一来,使用 Eloquent 就有点奇怪了,就像Restriction
从 a 中访问 aMachine / Product
或反之一样,并不容易:
Restriction::where('machine_product_id', Machine::find(1)->products()->first()->pivot->id );
如果我从给定的中得到 aProduct
或,我将不得不从我所拥有的 Restriction 的行中找到 'machine_id' 和 'product_id' 。Machine
Restriction
machine_product_id
我不知道在使用 Eloquent 时是否出于实用性和功能性问题,最好使用 . 做两个多对多表machine_id and product_id
,一个使用 the price (machine_products)
,另一个使用day, begin_hour, end_hour (restrictions)
. 第一个表是 1 到 1(machine_products)和另一个 1 到 N(限制)。我是说:
machine_products
给定特定的 machine_id 和 product_id,将只有一个价格。restrictions
给定特定的 machine_id 和 product_id,将有 N 行由 day、begin_hour、end_hour 组成。
或者如果我制作一个名为 的模型会更好MachineProduct
?我不知道...
你能告诉我或推荐解决这个困境的最佳方法吗?已经在修改表格、模型或任何需要的东西。
谢谢你。
解决方案
如果您仅对Machine和Product实体应用严格的实体关系设计,则中间表将只有两列。
machine_id INT PK FK to machine.id
product_it INT PK FK to product.id
这实现了Machine :: many-to-many :: Product
关系。
这个中间表将有一个复合主键。主键的唯一性将决定每台机器只能与每个产品有一个关系。通过插入一行来创建关系,并通过删除该行来切断它。
但是您的实际应用程序中还有两件事,价格和限制。看起来您的应用程序规定价格与机器和产品都有关系。
因此,我们需要另一个实体来清楚地描述您的应用程序。我们称它为Job。每个 Job 都有一个price
属性。它使用一台机器生产一种产品。因此,它具有这些关系。
Machine :: many-to-one :: Job
Product :: many-to-one :: Job
因此,您的 machines_products
表不是纯粹的多:多中间表。相反,它是并且应该称为 Job 表(或者如您所说的 MachineProduct 表)。
最后,你有一个具有这种关系的 Restriction 实体
Job :: one-to-many :: Restriction
因此,为了让您的 Eloquent 模型对现实世界更加清晰,请将 Job (MachineProduct) 实体添加到您的模型中。整个模型看起来像这样。(有趣的是,它的核心是 Job / MachineProduct 实体。)
+-------------+ +------------+ +---------------+
| | /| |\ | |
| Product |-----| Job |-----| Machine |
| | \| |/ | |
+-------------+ +------------+ +---------------+
|
|
/|\
+-------------+
| |
| Restriction |
| |
+-------------+
专业提示:最好在开始创建表格之前弄清楚您的实体和关系。
专业提示:如果您避免使用类似的列名,您的数据库架构可能更容易理解machine.id
,而是使用machine.machine_id
. 这样你就可以在查询中说这样的话
FROM Job j JOIN Machine m ON j.machine_id = m.machine_id
代替
FROM Job j JOIN Machine m ON j.machine_id = m.id
并且不必怀疑,等待,那id
是什么,也不要冒险错误地这样做:
FROM Job j JOIN Product p ON j.machine_id = p.id /* wrong */
推荐阅读
- xml - 查看使用 ant xml 制作的目录的内容
- c# - 在 Unity 中使用脚本重置相机的问题
- python - Scapy 中的位域
- jenkins - Jenkins JIRA 问题更新插件返回 400 错误
- sql-server - 无法创建表,因为主键在另一个表中用作外键
- r - 计算因子的出现次数、逗号分隔和条件?在 R 中
- java - 从文件读取的数据在冒泡排序方法中不起作用
- xcode - 如何修复以下错误:““无法将 'ViewController' 类型的值分配给类型 'UITextFieldDelegate?'”?
- java - 从 SDK 中运行 java exe
- java - 如何在每个数组中放置月份?