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

Mysql 我应该使用触发器连接两个相关但严重非规范化的表吗?,mysql,triggers,denormalization,Mysql,Triggers,Denormalization,我以前从未使用过触发器,但这似乎是一个可靠的用例。我想知道触发器是否是我应该使用的,如果是的话,我可以用一只小手来控制它 本质上,我有两个高度非规范化的表,goals和users\u goals。两者都有重复标题数据的标题列(VARCHAR)。因此,“学习如何使用触发器”将是一个主要目标,许多(在本例中可能不是很多)用户的目标都具有相同的标题。网站的架构要求做到这一点 我还不需要在这两个表之间建立关系。我将单个用户的目标链接到主要目标,但只需通过标题查询即可(在title列上有索引)现在我需要第

我以前从未使用过触发器,但这似乎是一个可靠的用例。我想知道触发器是否是我应该使用的,如果是的话,我可以用一只小手来控制它

本质上,我有两个高度非规范化的表,
goals
users\u goals
。两者都有重复
标题
数据的
标题列(
VARCHAR
)。因此,“学习如何使用触发器”将是一个主要目标,许多(在本例中可能不是很多)用户的目标都具有相同的标题。网站的架构要求做到这一点

我还不需要在这两个表之间建立关系。我将单个用户的目标链接到主要目标,但只需通过标题查询即可(在
title
列上有
索引
现在我需要第三个表来关联这两个表,但它只需要最终保持一致。将有两列,都是
外键
s、
goal\u id
users\u goal\u id


触发器是解决这个问题的方法吗?如果是这样,那会是什么样子?

是的,您可以使用触发器来实现,但具体的实现取决于您的需求

如果您想重新生成所有查询,因此它们不使用连接的标题,而是使用目标id,那么您可以直接构建它。如果你还需要保持标题同步,那是额外的

首先加入。您声明一个
目标
有许多
用户目标
。这是否意味着每个
用户目标
只属于一个
目标
?如果是这样,你就不需要额外的桌子了。您只需将一列
goal\u id
添加到
user\u goals
表中即可。确保存在外键约束(我希望您使用的是InnoDB表),以便可以强制执行引用完整性

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

  • 更新
    目标
    表上的触发器。修改标题时,此触发器应更新相关的
    user\u goals
  • 更新
    user\u goals
    表上的触发器。如果修改了
    user\u goals.title
    ,此触发器应检查
    goals
    表中的标题是否与
    user\u goals
    中的新标题不同。如果是,您有两个选择:
  • 例外:不允许在user_goals子表中修改标题
  • 更新:允许更改标题。更新目标中的父记录。目标触发器将为您更新其他相关的用户目标
  • 您也可以通过在触发器中重新更改值来忽略更改,但这不是一个好主意
  • 用户目标上插入触发器
    。最简单的选项是查询指定的
    目标id
    的标题,并且不允许为标题插入其他值。如果给出了标题,您可以选择更新
    目标
  • 在目标上插入触发器。不需要这个

  • 不,如果可以避免的话,你根本不应该使用触发器

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

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

    如果需要多个客户端代码更新表,请考虑使用存储过程;将其记录在代码维护手册(以及注释等)中,以确保未来的开发人员也这样做

    如果您可以不受影响,只需在客户端编写一个公共例程,它总是被调用来更新共享列


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

    好吧,我之所以避免这种架构,是因为(常见的)标题修改情况。这可能是用户编辑目标时最常见的一件事。在这种情况下,第二个触发器中的三个子选项都不是理想的。它现在的工作方式是将一个新标题插入到
    users\u goals
    表中,如果
    goals
    中没有具有该标题的目标,那么也会在那里创建一个具有该标题的目标。因此,
    users\u goals
    中的特定行将保持相同的ID,但可能会经过数百次
    title
    修改。至于您的第一个触发器,我也不希望在用户在
    users\u goals
    中更改其目标的标题时,
    goals
    标题可以修改。你可以想象这样一种情况,你的目标是“学会唱歌”,我也有这个目标,我将它的标题更新为“学会唱歌剧”,这也会触发你目标的标题更改。顺便说一句,我正在使用InnoDB处理所有事情。啊。您对一个主要目标的描述有许多用户目标,我将其解释为用户目标,即目标的子表。在这种情况下,您可以假设始终存在一个目标(您可以在目标id中找到)。在你的情况下你也可以这样做,但这可能会给你带来一些问题。一次输入将创建一个新目标,而不是将用户目标链接到现有目标。也许你最好也修改你的界面,允许用户添加用户目标