【问题标题】:How to determine if a field/column is affected by an UPDATE statement如何确定字段/列是否受 UPDATE 语句影响
【发布时间】:2011-05-06 05:22:47
【问题描述】:

大家好,感谢您的回答和cmets。

我有一个包含几个字段的表,其中有versionlast_modifiedmodified_by

我正在编写一个触发器:

  • 在每次/任何更新后将 version 增加 1,
  • last_modified设置为当前时间戳,
  • 将进行最新更改的用户的ID设置为modified_by,并
  • 通过引发信号(在这种情况下)防止程序员忽略/忘记在 UPDATE 语句中设置 modified_by = userid

我怎样才能做到这一点?

我尝试检查isnull(NEW.modified_by),但随后意识到NEW.modified_byOLD.modified_by 具有相同的值,如果它不受影响。此外,检查NEW.modified_by 是否等于OLD.modified_by 也不太成功,因为它可能是用户修改了之前自己修改过的记录。

有没有办法确定哪些字段受 UPDATE 语句影响?或者某个特定字段 (modified_by) 是否受到影响?

【问题讨论】:

    标签: mysql sql stored-procedures triggers


    【解决方案1】:

    我找不到任何可以让您检查传入信息以查看哪些字段受到影响的信息。虽然我知道您正试图在触发器级别停止此问题,但要求所有表写入都通过存储过程可能是谨慎的。这样你就可以要求用户字段。

    如果这不可能,我认为您可能需要变得棘手。例如,您可以要求将 user_id 写入两个字段(为此创建一个额外的空白列)。然后,将虚拟列中的 user_id 与您正在更新的用户进行比较。一旦确定是否需要修改 user_id,请再次空白列。它不漂亮,但它可以完成工作。

    【讨论】:

    • 由于这些完全相同的修改(相同的行为,相同的字段)发生在几个表上,我正在做的是为每个表创建一个更新触发器,但实际发生的是每个触发器 检查它是否可以继续或需要发出信号,然后调用相同的存储过程(执行实际工作)。注意:我将在编辑中发布脚本。
    • 我会接受你的第二个建议(有点)。我要做的是有一个虚拟列,它总是为空的。它必须在更新期间设置。我将检查新值是否有效或为空。如果它为空,我会发出信号。如果有效,我会将其存储在适当的字段中。最后,我会将虚拟字段重置为空。有什么想法吗?
    • 这就是我想要解释的。我相信这对你有用。让我知道结果如何。
    【解决方案2】:

    我遇到了类似的问题。我有一个表,其中包含一个名为 isDirty 的 tinyint 列,并且希望在更新行时将其设置为 1,并在“清理”行时将其清除为 0。

    问题是,值 0 和 1 的 NEW 和 OLD 的组合并没有给我足够的值来解决我的问题。因此,我制定了一个“规则”,即当列更新为值 100 时,它被设置为“0”的干净值,其他任何东西都将其设置为“1”。这样做的原因是该列将只有 2 个值之一,0 或 1,因此您可以使用 100(或您选择的任何值)作为指示它是干净的“标志”。

    我知道将其设置为非零值以返回 0 听起来有点倒退,但这是我选择的方向并且它有效。这是触发器的样子:

    CREATE TRIGGER calls_update BEFORE UPDATE ON `calls`
        FOR EACH ROW
        BEGIN
            IF ( NEW.isDirty = 100 ) THEN
                SET NEW.isDirty = 0;
        ELSE
                SET NEW.isDirty = 1;
            END IF;
        END
    $$
    

    【讨论】:

    • 感谢您的意见@Bill,但我认为您在这里有点偏离主题(或者只是我不理解您的方法)。您的建议没有解决我所针对的问题,即:- 通过发出信号(在这种情况下)来防止程序员忽略/忘记在 UPDATE 语句中设置modified_by = userid。像您这样的解决方案很容易被覆盖:程序员可以简单地将 100、0、1 或更糟的任何其他未管理(预期)的数字插入到 isDirty 字段中,而在 modified_by 字段中没有任何内容。如果我在这里遗漏了什么,请您详细说明一下吗?
    【解决方案3】:

    据我所知,您唯一的选择是对照 OLD 检查每列的 NEW 值。

    SET `ColumnAChanged` = NEW.ColumnA <=> OLD.ColumnA;
    SET `ColumnBChanged` = NEW.ColumnB <=> OLD.ColumnB;
    

    【讨论】:

    • 我想过这样做,但是如果新值与旧值相同就可以了:可能是用户修改了自己之前修改过的记录。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-01-02
    • 2013-01-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-07
    • 1970-01-01
    相关资源
    最近更新 更多