更新:下面的模式只是一个需要与其他模块具有多态关系的模块(注解)的简化示例。该应用程序有许多模块(30+)和用户可以通过管理添加新的模块。因此,每个模块都可以“链接”到另一个模块,但是我们在编码时不知道模块名和表名。因此,我们需要一个多态关系。
我正在尝试使用多态关联对动态表名执行连接。
假设以下mysql表
modules table
module_id | name | table_name
1 | Quote | quotes
2 | Order | orders
3 | Product | products
注意:系统允许通过admin添加新模块,因此我们在编码时不知道表名和列名。对于现有模块,模块名或表名也可以随时间而更改。
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类名或表名直接存储在父表上,允许多态关系。
这就让orm来处理这种关系,据我所知,通常会带来一些性能代价。我认为性能会受到显著影响的原因有:
雄辩的头顶。对于1000行,它将为每行创建一个有说服力的对象。我喜欢雄辩,但在检索大量行时,它的性能远远不够理想。查询生成器更适合这种情况,但不支持多态性。
既然这个关联是在雄辩的层面上完成的,我相信它将需要一个额外的查询。我还没有测试过这个,但是,否则,雄辩者怎么知道要加入哪些表呢?我很高兴在这件事上弄错了。
有时还可能导致其他维护问题,例如更新表名或更改orm类名/命名空间(尽管有解决方案)。
这将绕过外键约束。
我通常不喜欢将表名或模型直接与记录表耦合的想法。这种方法的另一个重要(至少对我来说)缺点是它将数据库模式与应用程序紧密耦合。或者换言之,靠的是雄辩的“魔力”。如果我们在某个时候想要利用node.js、python或golang(我们目前正在实现一个microservices架构),我们可能无法使用它,必须重新构造代码和数据库。
我很少读过像这篇或这篇这样的文章和问题。
我想到的一种方法是使用mysql函数或存储过程动态获取表名并连接结果。我能够使用存储过程和函数动态地获取表名,但似乎不可能连接存储过程的结果。函数似乎不能很好地解决这个问题。
第二种方法是将记录名保存在一个单独的表中。这对获取整个记录(引号、订单等)不起作用,但由于我只需要记录名,所以它工作得很好(当然有适当的索引)。
record_name table
module_id | record_id | name
1 | 23 | Quote #Q-23
2 | 122 | Order #O-122
3 | 55 | Product #P-55
这种方法有一些缺点-第一,它只适用于获取选定的键(在本例中为name)。第二是重复数据和违反其他数据库原则。最后,更新module\u name表需要维护。
因此,我的问题如下—
有没有好的替代方法可以在数据库级别(mysql)或必须在应用程序级别对这种关系进行建模?
mysql存储过程或函数能解决这个问题吗?
1条答案
按热度按时间ewm0tg9j1#
您的模式是错误的,当您检查
comments.record_id
.修复外键约束,结果应该是这样的:
正确的数据库模式(关系)比laravel/雄辩的魔力更重要。事实上,更少的魔法更容易和更好的工作。您还应该考虑根本不使用这种数据库抽象,它不会使事情变得更简单,只会带来问题。
另一种可能更好的方法是使用关系表:
)