我应该使用触发器来连接两个相关但严重非规范化的表吗?

发布于 2024-10-03 07:07:43 字数 588 浏览 3 评论 0原文

我以前从未使用过触发器,但这似乎是一个可靠的用例。我想知道触发器是否是我应该使用的,如果是的话,我可以稍微指导一下如何去做。

本质上,我有两个严重非规范化的表goalsusers_goals。两者都有重复 title 数据的 title 列 (VARCHAR)。因此,将有一个主要目标“学习如何使用触发器”,并且许多(好吧,在这种情况下可能不是很多)用户的目标具有相同的标题。站点的架构要求如此。

我还不需要在这两个表之间建立关系。我将个人用户的目标链接到主要目标,但只需通过标题查询(在 title 列上使用 INDEX)即可实现此目的。 现在我需要有第三个表来关联这两个表,但它只需要最终一致。将有两列,均为 FOREIGN KEYgoal_idusers_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 KEYs, goal_id and users_goal_id.

Are triggers the way to go with this? And if so, what would that look like?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

怪我太投入 2024-10-10 07:07:43

是的,您可以使用触发器来执行此操作,但具体实施取决于您的需求。

如果您想重建所有查询,以便它们不使用连接标题,而是使用 goal_id,您可以构建它。如果您还需要保持标题同步,则需要额外付费。

首先是为了加入。您说过一个目标有多个用户目标。这是否意味着每个用户目标只属于一个目标?如果是这样,您就不需要额外的桌子。您只需向 user_goals 表中添加一列 goal_id 即可。确保有外键约束(我希望你使用的是 InnoDB 表),这样你就可以强制引用完整性。

然后触发。我不太确定如何在 MySQL 上编写它们。我在 Oracle 上经常使用触发器,但在 MySQL 上很少使用。无论如何,我建议您构建三个触发器:

  1. 更新 goals 表上的触发器。当标题修改时,此触发器应更新相关的 user_goals 表。
  2. 更新 user_goals 表上的触发器。如果 user_goals.title 被修改,此触发器应检查 goals 表中的标题是否与 user_goals 中的新标题不同。如果是这样,您有两个选择:
    1. 例外:不允许在 user_goals 子表中修改标题。
    2. 更新:允许更改标题。更新目标中的父记录。目标触发器将为您更新其他相关的 user_goals。
    3. 您也可以通过将值更改回触发器中来默默地忽略更改,但这不是一个好主意。
  3. user_goals 上插入触发器。最简单的选择是查询指定 goal_id 的标题,并且不允许插入另一个标题值。如果给出标题,您可以选择更新目标
  4. 在目标上插入触发器。不需要这个。

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 many user goals. Does that mean that each user goal belongs to only one goal? If so, you don't need the extra table. You can just add a column goal_id to your user_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:

  1. Update trigger on goals table. This trigger should update related user_goals table when the title is modified.
  2. Update trigger on the user_goals table. If user_goals.title is modified, this trigger should check if the title in the goals table differs from the new title in user_goals. If so, you have two options:
    1. Exception: Don't allow the title to be modified in the user_goals child table.
    2. Update: Allow the title to be changed. Update the parent record in goals. The trigger on goals will update the other related user_goals for you.
    3. You could also silently ignore the change by changing the value back in the trigger, but that wouldn't be a good idea.
  3. Insert trigger on user_goals. Easiest option is to query the title of the specified goal_id and don't allow inserting another value for title. You could opt to update goals if a title is given.
  4. Insert trigger on goals. No need for this one.
以为你会在 2024-10-10 07:07:43

不,如果可以避免,您根本不应该使用触发器。

对我来说,触发器是一种反模式;它们具有“在程序员背后做事”的效果。

想象一下,您的应用程序的未来维护者需要做一些事情,如果他们不知道触发器(想象一下他们没有详细检查您的数据库模式创建脚本),那么他们可能会花费很长很长时间试图找出原因这种情况发生了。

如果您需要多段客户端代码来更新表,请考虑让它们使用存储过程;在代码维护手册(和注释等)中记录这一点,以确保未来的开发人员也这样做。

如果您可以摆脱它,只需在客户端编写一个通用例程,该例程总是被调用来更新共享列。

即使触发器也无法确保列始终同步,因此您需要实施一个定期过程来检查这一点。否则它们迟早会失去同步(也许只是因为某些操作工程师决定开始进行手动更新;也许一个表从备份中恢复,而另一个则没有)

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)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文