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?
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:
- Update trigger on
goals
table. This trigger should update relateduser_goals
table when the title is modified. - Update trigger on the
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:- Exception: Don't allow the title to be modified in the user_goals child table.
- 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.
- You could also silently ignore the change by changing the value back in the trigger, but that wouldn't be a good idea.
- Insert trigger on
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. - Insert trigger on goals. No need for this one.
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)
精彩评论