MySQL:引用删除触发器中的当前行

时间:2017-04-28 22:04:10

标签: mysql triggers sql-delete

我在MySQL中AFTER DELETE触发器中引用当前行时遇到问题。假装我有以下books表:

+----+------+----------+
| id | name | ordering |
+----+------+----------+
| 1  | It   | 3        |
| 2  | Cujo | 1        |
| 3  | Rage | 2        |
+----+------+----------+

我想创建一个触发器,它会减少ordering值大于删除行中ordering值的所有行。例如,如果我DELETE FROM books WHERE id = 2,我希望结果表看起来像:

+----+------+----------+
| id | name | ordering |
+----+------+----------+
| 1  | It   | 2        |
| 3  | Rage | 1        |
+----+------+----------+

我试过了:

DROP TRIGGER IF EXISTS reorder_books_on_delete;
DELIMITER $$
CREATE TRIGGER reorder_books_on_delete 
AFTER DELETE ON books 
FOR EACH ROW 
BEGIN 
    IF ordering > OLD.ordering 
    THEN 
        UPDATE books SET ordering = ordering - 1 
        WHERE id = id;
    END IF; 
END$$
DELIMITER ;

但是当我在桌面上执行DELETE时,这会导致错误:

  

ERROR 1054(42S22):未知列'订购'在' where子句'

这是指if语句,那么如何引用ON DELETE触发器中的当前行?该列肯定存在。

2 个答案:

答案 0 :(得分:1)

它失败的原因是因为没有current行,因此ordering列不存在,它应该在WHERE子句中使用,如下所示:

DROP TRIGGER IF EXISTS reorder_books_on_delete;
DELIMITER $$
CREATE TRIGGER reorder_books_on_delete 
AFTER DELETE ON books 
FOR EACH ROW 
BEGIN 
     UPDATE books SET ordering = ordering - 1 
     WHERE ordering > OLD.ordering;
END$$
DELIMITER ;

但是,根据MySQL的documentation,您无法执行此操作,它将返回以下错误:

  

SQL错误(1442):无法更新已存储的表“书籍”   函数/触发器,因为它已被调用的语句使用   这个存储的函数/触发器。

因此,您必须在单个事务中UPDATE查询后运行另一个DELETE查询才能实现此功能。

答案 1 :(得分:1)

如Darshan所说,你不能用触发器做到这一点......但是,程序可以为你制造!

DROP PROCEDURE IF EXISTS delete_book;
DELIMITER //

CREATE PROCEDURE delete_book(IN pId INT)
BEGIN
    set @a = (
        SELECT ordering
        FROM books
        WHERE id = pId
        );

    UPDATE books SET ordering = ordering - 1 
    WHERE ordering  > @a;

    delete from books
    WHERE id = pId;

END 
//
DELIMITER ;

而你只是而不是DELETE FROM books WHERE id = 4来制作CALL delete_book(4);