更新: 以下架构只是一个模块(注释)的简化示例,该模块需要与其他模块具有多态关系。该应用程序有许多模块(超过30个),用户可以通过admin添加新模块。因此,每个模块都可以“链接”到另一个模块,但是在编码时我们还不知道模块名称和表名称。因此,我们需要一个多态关系。
我正在尝试使用多态关联对动态表名称执行联接。
假设以下MySQL表
modules table
module_id | name | table_name
1 | Quote | quotes
2 | Order | orders
3 | Product | products
注意:系统允许通过admin添加新模块,因此在编码时我们不知道表名和列名。对于现有模块,模块名称或table_name也可以随时间变化。
quotes table
id | name
22 | "Quote #Q-22"
23 | "Quote #Q-23"
orders table
id | name
122 | "Order #O-122"
123 | "Order #O-123"
products table
id | name
55 | "Product #P-55"
56 | "Product #P-56"
comments table
id | module_id | record_id | text
1 | 1 | 23 | hello
2 | 2 | 122 | big
3 | 3 | 55 | world
我想运行一个查询,该查询将返回以下行:
comments
id | name | text
1 | Quote #Q-23 | hello
2 | Order #O-122 | big
3 | Product #P-55 | world
Laravel通过将ORM类名或表名直接存储在父表中来允许polymorphic relationship。
这让ORM负责处理这种关系,据我所知,通常会附带一些性能价格。 我认为会有明显的性能下降的原因是:
我通常不喜欢将表名或模型直接与记录表耦合的想法。 这种方法的另一个重要(至少对我而言)缺点是,它将数据库模式与应用程序紧密耦合。换句话说,就是依靠口才的“魔术”。如果我们在某个时候想利用Node.js,Python或GoLang(我们目前正在实现微服务架构),我们可能将无法使用它,而不得不重组代码和数据库。
我已经阅读了几篇其他文章和问题,例如this one或this one。
我想到的一种方法是使用MySQL函数或存储过程来动态获取表名称并合并结果。我能够使用存储过程和函数来动态获取表名,但是似乎无法加入存储过程的结果。函数似乎也不能解决这个问题。
第二种方法是将记录名称保存在单独的表中。这对于获取整个记录(行情,订单等)不起作用,但是由于我只需要记录名称,因此它可以正常工作(当然具有适当的索引编制)。
record_name table
module_id | record_id | name
1 | 23 | Quote #Q-23
2 | 122 | Order #O-122
3 | 55 | Product #P-55
此方法有一些缺点-首先,它仅适用于获取选定的键(在这种情况下为名称)。第二点是它复制数据并违反其他数据库原则。最后,需要维护才能更新module_name表。
因此,我的问题如下-
答案 0 :(得分:-1)
您的架构是错误的,当您检查comments.record_id
的外键约束时,您会注意到。
修复外键约束,并且应该出现类似这样的内容:
comments table
id | quotes_id | orders_id | products_id | text
1 | 22 | null | null | Text comment
2 | null | 122 | null | Text comment
3 | null | null | 55 | Text comment
正确的数据库架构(关系)比Laravel /雄辩的魔术更为重要。实际上,更少的魔术更容易更好地使用。 您还应该考虑完全不使用这种数据库抽象,它不会使事情变得简单,只会带来问题。
一种不同甚至更好的方法是使用关系表:
- comments table
id | text
1 | hello
2 | world
- quote_has_comment table
quote_id | comment_id
22 | 1
(with constraint quote_id+comment_id beeing unique
)