我遇到一种情况,即如果满足某个条件,我不希望发生插入(事务应该回滚)。我可以在应用程序代码中编写这个逻辑,但是出于某种原因说,它必须用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;
您可以保证:
问题:您是否在第一种方法中看到任何令人反感的内容?
答案 0 :(得分: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。
答案 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;