mysql和触发器使用问题

时间:2010-06-10 17:42:48

标签: mysql triggers check-constraints

我遇到一种情况,即如果满足某个条件,我不希望发生插入(事务应该回滚)。我可以在应用程序代码中编写这个逻辑,但是出于某种原因说,它必须用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 个答案:

答案 0 :(得分:1)

来自trigger documentation

  

触发器不能使用显式或隐式开始或结束事务的语句,例如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。

答案 1 :(得分:0)

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

CREATE TRIGGER t1 BEFORE INSERT ON table1
FOR EACH ROW
  IF (condition) THEN
    SELECT 1/0 FROM table1 LIMIT 1
  END IF;
END;