0

我有一种情况,如果满足某个条件,我不希望发生插入(事务应该回滚)。我可以在应用程序代码中编写这个逻辑,但是由于某种原因,它必须用 MySQL 本身编写(比如用不同语言编写的客户端将插入到这个 MySQL InnoDB 表中)[这是一个单独的讨论]。

表定义:

CREATE TABLE table1(x int NOT NULL);

触发器看起来像这样:

CREATE TRIGGER t1 BEFORE INSERT ON table1
FOR EACH ROW
  IF (condition) THEN
    NEW.x = NULL;
  END IF;
END;

我猜它也可以写成(未经测试):

CREATE TRIGGER t1 BEFORE INSERT ON table1
FOR EACH ROW
  IF (condition) THEN
    ROLLBACK;
  END IF;
END;

但是,这不起作用:

CREATE TRIGGER t1 BEFORE INSERT ON table1 ROLLBACK;

您得到保证:

  1. 您的数据库将永远是 MySQL
  2. 表类型将始终为 InnoDB
  3. NOT NULL 列将始终保持原样

问题:您在第一种方法中看到任何令人反感的地方吗?

4

2 回答 2

1

触发器文档

触发器不能使用显式或隐式开始或结束事务的语句,例如 START TRANSACTION、COMMIT 或ROLLBACK

无法创建您的第二个选项。然而:

触发器失败会导致语句失败,因此触发器失败也会导致回滚。

因此,Eric 建议使用保证会导致错误的查询是下一个选择。然而,MySQL 不具备引发自定义错误的能力——您将需要处理误报。由于缺乏自定义错误处理,封装在存储过程中不会更好......

如果我们更详细地了解您的情况,则有可能通过约束来处理。

更新


我已经确认虽然 MySQL 有 CHECK 约束语法,但它并没有被任何引擎强制执行。如果锁定对表的访问,则可以在存储过程中处理限制逻辑。以下触发器不起作用,因为它引用了要插入的表:

CREATE TRIGGER t1 BEFORE INSERT ON table1
FOR EACH ROW

  DECLARE num INT;
  SET num = (SELECT COUNT(t.col)
              FROM your_table t
             WHERE t.col = NEW.col);

  IF (num > 100) THEN
    SET NEW.col = 1/0;
  END IF;

END;

..导致 MySQL 错误 1235。

于 2010-06-10T18:09:56.973 回答
0

您是否尝试过引发错误以强制回滚?例如:

CREATE TRIGGER t1 BEFORE INSERT ON table1
FOR EACH ROW
  IF (condition) THEN
    SELECT 1/0 FROM table1 LIMIT 1
  END IF;
END;
于 2010-06-10T17:52:05.277 回答