我应该使用触发器来连接两个相关但严重非规范化的表吗?
我以前从未使用过触发器,但这似乎是一个可靠的用例。我想知道触发器是否是我应该使用的,如果是的话,我可以稍微指导一下如何去做。
本质上,我有两个严重非规范化的表:goals
和users_goals
。两者都有重复 title
数据的 title
列 (VARCHAR
)。因此,将有一个主要目标“学习如何使用触发器”,并且许多(好吧,在这种情况下可能不是很多)用户的目标具有相同的标题。站点的架构要求如此。
我还不需要在这两个表之间建立关系。我将个人用户的目标链接到主要目标,但只需通过标题查询(在 title
列上使用 INDEX
)即可实现此目的。 现在我需要有第三个表来关联这两个表,但它只需要最终一致。将有两列,均为 FOREIGN KEY
、goal_id
和 users_goal_id
。
触发器是解决这个问题的方法吗?如果是这样,那会是什么样子?
I've never used triggers before, but this seems like a solid use case. I'd like to know if triggers are what I should be using, and if so, I could use a little hand-holding on how to go about it.
Essentially I have two heavily denormalized tables, goals
and users_goals
. Both have title
columns (VARCHAR
) that duplicate the title
data. Thus, there will be one main goal of "Learn how to use triggers", and many (well, maybe not many in this case) users' goals with the same title. The architecture of the site demands that this be the case.
I haven't had a need to have a relationship between these two tables just yet. I link from individual users' goals to the main goals, but simply do so with a query by title, (with an INDEX
on the title
column). Now I need to have a third table that relates these two tables, but it only needs to be eventually consistent. There would be two columns, both FOREIGN KEY
s, goal_id
and users_goal_id
.
Are triggers the way to go with this? And if so, what would that look like?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
是的,您可以使用触发器来执行此操作,但具体实施取决于您的需求。
如果您想重建所有查询,以便它们不使用连接标题,而是使用 goal_id,您可以构建它。如果您还需要保持标题同步,则需要额外付费。
首先是为了加入。您说过一个
目标
有多个用户目标
。这是否意味着每个用户目标
只属于一个目标
?如果是这样,您就不需要额外的桌子。您只需向user_goals
表中添加一列goal_id
即可。确保有外键约束(我希望你使用的是 InnoDB 表),这样你就可以强制引用完整性。然后触发。我不太确定如何在 MySQL 上编写它们。我在 Oracle 上经常使用触发器,但在 MySQL 上很少使用。无论如何,我建议您构建三个触发器:
goals
表上的触发器。当标题修改时,此触发器应更新相关的user_goals
表。user_goals
表上的触发器。如果user_goals.title
被修改,此触发器应检查goals
表中的标题是否与user_goals
中的新标题不同。如果是这样,您有两个选择:user_goals
上插入触发器。最简单的选择是查询指定goal_id
的标题,并且不允许插入另一个标题值。如果给出标题,您可以选择更新目标
。Yes you could do this using triggers, but the exact implementation depends on your demands.
If you want to rebuild al your queries, so they don't use the title for the join, but the goal_id instead, you can just build that. If you need to keep the titles in sync as well, that's an extra.
First for the join. You stated that one
goal
has manyuser goals
. Does that mean that eachuser goal
belongs to only onegoal
? If so, you don't need the extra table. You can just add a columngoal_id
to youruser_goals
table. Make sure there is a foreign key constraint (I hope you're using InnoDB tables), so you can enforce referential integrity.Then the trigger. I'm not exactly sure how to write them on MySQL. I do use triggers a lot on Oracle, but only seldom on MySQL. Anyway, I'd suggest you build three triggers:
goals
table. This trigger should update relateduser_goals
table when the title is modified.user_goals
table. Ifuser_goals.title
is modified, this trigger should check if the title in thegoals
table differs from the new title inuser_goals
. If so, you have two options:user_goals
. Easiest option is to query the title of the specifiedgoal_id
and don't allow inserting another value for title. You could opt to updategoals
if a title is given.不,如果可以避免,您根本不应该使用触发器。
对我来说,触发器是一种反模式;它们具有“在程序员背后做事”的效果。
想象一下,您的应用程序的未来维护者需要做一些事情,如果他们不知道触发器(想象一下他们没有详细检查您的数据库模式创建脚本),那么他们可能会花费很长很长时间试图找出原因这种情况发生了。
如果您需要多段客户端代码来更新表,请考虑让它们使用存储过程;在代码维护手册(和注释等)中记录这一点,以确保未来的开发人员也这样做。
如果您可以摆脱它,只需在客户端编写一个通用例程,该例程总是被调用来更新共享列。
即使触发器也无法确保列始终同步,因此您需要实施一个定期过程来检查这一点。否则它们迟早会失去同步(也许只是因为某些操作工程师决定开始进行手动更新;也许一个表从备份中恢复,而另一个则没有)
No, you should never use triggers at all if you can avoid it.
Triggers are an anti-pattern to me; they have the effect of "doing stuff behind the programmer's back".
Imagine a future maintainer of your application needs to do something, if they are not aware of the trigger (imagine they haven't checked your database schema creation scripts in detail), then they could spend a long, long time trying to work out why this happens.
If you need to have several pieces of client-side code updating the tables, consider making them use a stored procedure; document this in the code maintenance manual (and comments etc) to ensure that future developers do the same.
If you can get away with it, just write a common routine on the client side which is always called to update the shared column(s).
Even triggers do nothing to ensure that the columns are always in sync, so you will need to implement a periodic process which checks this anyway. They will otherwise go out of sync sooner or later (maybe just because some operations engineer decides to start doing manual updates; maybe one table gets restored from a backup and the other doesn't)