我试图通过使用before delete触发器避免在mysql中一次删除超过1行。
示例表和触发器如下所示。
表测试:
DROP TABLE IF EXISTS `test`;
CREATE TABLE `test` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`a` int(11) NOT NULL,
`b` int(11) NOT NULL,
PRIMARY KEY (`id`));
INSERT INTO `test` (`id`, `a`, `b`)
VALUES (1, 1, 2);
INSERT INTO `test` (`id`, `a`, `b`)
VALUES (2, 3, 4);
触发:
DELIMITER //
DROP TRIGGER IF EXISTS prevent_multiple_deletion;
CREATE TRIGGER prevent_multiple_deletion
BEFORE DELETE ON test
FOR EACH STATEMENT
BEGIN
IF(ROW_COUNT()>=2) THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = 'Cannot delete more than one order per time!';
END IF;
END //
DELIMITER ;
这仍然允许删除多行。即使我将if改为>=1,仍然允许该操作。
我的想法是避免以下操作:
DELETE FROM `test` WHERE `id`< 5;
你能帮助我吗?我知道mysql的当前版本不允许每个语句触发。
谢谢您!
1条答案
按热度按时间new9mtju1#
首先,从您最初的尝试中排除一些语法错误:
而不是
FOR EACH STATEMENT
,应该是FOR EACH ROW
.因为您已经将分隔符定义为
//
; 你需要使用//
(代替;
)在DROP TRIGGER IF EXISTS ..
声明。Row_Count()
将在Before Delete Trigger
,因为尚未更新任何行。所以这种方法行不通。现在,这里的技巧是使用会话级可访问(和持久)的用户定义变量。我们可以定义一个变量
@rows_being_deleted
,稍后检查是否已定义。For Each Row
为要删除的每一行运行相同的语句集。所以,我们只检查session变量是否已经存在。如果没有,我们可以定义它。所以基本上,对于第一行(被删除),它将被定义,只要会话在那里,它就会一直存在。现在,如果有更多的行要删除,触发器将为其余的行运行相同的语句集。在第二行中,可以找到先前定义的变量,我们现在可以简单地抛出一个异常。
请注意,在同一会话中,可能会触发多个delete语句。所以在抛出异常之前,我们需要设置
@rows_being_deleted
价值回归null
.以下将起作用:
db fiddle演示1:尝试删除多行。
结果:
查询错误:错误:er\u信号\u异常:一次不能删除多个订单!
db fiddle演示2:尝试只删除一行
查询#1
删除成功。我们可以使用
Select
.查询#2