BEFORE UPDATE 触发器阻止所有更新

Posted

技术标签:

【中文标题】BEFORE UPDATE 触发器阻止所有更新【英文标题】:BEFORE UPDATE trigger preventing all updates 【发布时间】:2018-05-16 14:31:50 【问题描述】:

我有一个包含许多列的表,我正在尝试实现一个触发器,该触发器在更新之前在特定列上工作,以确保该特定列的值只能根据一个特定的过渡,从 1 到 2 到 3。

例如,如果我的列中的值为 1,则如果尝试将其从 1 更改为 3,则对该列的更新将被拒绝,但如果它从 1 更改为 2,则该列的更新将被接受。

下面的代码有效,但是,它当前拒绝所有不符合该代码的更新。例如,如果我尝试更新该表中不同列的行,我的更新将被拒绝,即使我没有以任何方式更改值列。

DELIMITER //
CREATE TRIGGER transition BEFORE UPDATE ON tbl
FOR EACH ROW
BEGIN
IF (OLD.value = 1 AND NEW.value != 2)
OR (OLD.value = 2 AND NEW.value != 3)
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = 'Incorrect transition of values';
END IF;
END //
DELIMITER;

如何解决此问题,以便在建立转换一致性的同时仍能更新其他列?

我正在使用 mariadb 5.5.50。

非常感谢!

【问题讨论】:

【参考方案1】:

这将使值保持不变:

CREATE TRIGGER transition BEFORE UPDATE ON tbl
FOR EACH ROW
BEGIN
  IF (OLD.value = 1 AND NEW.value NOT IN (1, 2))
  OR (OLD.value = 2 AND NEW.value NOT IN (2, 3))
  THEN
    SIGNAL SQLSTATE '45000'
    SET MESSAGE_TEXT = 'Incorrect transition of values';
  END IF;
END// 

我对此进行了测试:

mysql> insert into tbl set value=1, other=11;
Query OK, 1 row affected (0.00 sec)

mysql> update tbl set other=22;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> update tbl set value=1, other=33;
Query OK, 1 row affected (0.01 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> update tbl set value=2, other=44;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> update tbl set value=1, other=55;
ERROR 1644 (45000): Incorrect transition of values

mysql> update tbl set value=2, other=66;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> update tbl set value=2, other=77;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> update tbl set value=3, other=88;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

但是在值为 3 之后会发生什么?它可以改变任何东西,还是必须保持3?您可能需要另一个术语来对此进行测试。

【讨论】:

感谢您的回答,但我希望能够从 1 --> 2 或 2 --> 3 更改该特定列中的值,但拒绝任何不符合的更改转换(例如,1 --> 3 [UPDATE tbl SET value = 3 WHERE value = 1,应该被拒绝)。目前,我的触发器对此进行了管理,但问题是我无法更新表中的任何其他列,即使它们没有更改“值”中的任何内容。我该如何解决这个问题? 我提供的解决方案符合您的要求。我在上面编辑了我的答案,以包括测试它的演示。

以上是关于BEFORE UPDATE 触发器阻止所有更新的主要内容,如果未能解决你的问题,请参考以下文章

如果 BEFORE 触发器产生错误,UPDATE 是不是仍然执行?

触发器before和after有啥区别?

Orcale触发器的after/before

触发器

如何创建触发器以检查更新的字段值

ORACLE PL/SQL BEFORE UPDATE触发器,判断要update的字段是不是符合null or not null规则, 如果符合update.