【问题标题】:How to write a trigger to abort delete in MYSQL?如何编写触发器以在 MYSQL 中中止删除?
【发布时间】:2011-09-29 10:06:14
【问题描述】:

我读过这个article,但它似乎不适用于删除。尝试创建触发器时出现此错误:

在服务器中执行 SQL 脚本

错误:错误 1363:DELETE 触发器中没有新行

CREATE TRIGGER DeviceCatalog_PreventDeletion 
BEFORE DELETE on DeviceCatalog
FOR EACH ROW
BEGIN
    DECLARE dummy INT;

    IF old.id = 1 or old.id =2 THEN
        SELECT * FROM DeviceCatalog WHERE DeviceCatalog.id=NEW.id;
    END IF;
END; 

SQL 脚本执行完成:语句:4 条成功,1 条失败

【问题讨论】:

  • NEW.fieldname 在插入或更新记录时存在;当您删除时,数据库中没有任何新内容!!!错误很明显:您不能使用 NEW.id,因为 DELETE 触发器中不允许使用 NEW
  • 根据链接的文章,select 语句应该失败 - 您的 select 语句读起来像真实的,而不像文章中打算失败的 select into dummy

标签: mysql triggers sql-delete


【解决方案1】:

使用@MathewFoscarini 对MySQL SIGNAL Command 的评论改进@Devart 的(已接受)答案,而不是通过调用不存在的过程引发错误,您可以发出自定义错误消息的信号。

DELIMITER $$

CREATE TRIGGER DeviceCatalog_PreventDeletion
BEFORE DELETE ON DeviceCatalog
FOR EACH ROW
BEGIN

  IF old.id IN (1,2) THEN -- Will only abort deletion for specified IDs
    SIGNAL SQLSTATE '45000' -- "unhandled user-defined exception"
      -- Here comes your custom error message that will be returned by MySQL
      SET MESSAGE_TEXT = 'This record is sacred! You are not allowed to remove it!!';
  END IF;

END
$$

DELIMITER ;

SQLSTATE 45000 被选为MySQL's Reference Manual 建议:

要发出通用 SQLSTATE 值的信号,请使用“45000”,这意味着“未处理的用户定义异常”。

这样,当用户尝试删除 ID 12 的记录时,您的自定义消息就会显示给用户。此外,如果不应从表中删除任何记录,您可以删除 IF .. THENEND IF; 行。这将防止 ANY 记录在表中被删除。

【讨论】:

  • 我无法让它与 jdbc 连接器一起使用。它抛出一个错误:createSQLException unknown table in a where 子句。
  • 你能澄清一下关于从表中删除任何记录的观点吗?如果我对多行运行单个删除查询,但只有一行触发条件,是否会删除其他行?
【解决方案2】:

试试这样的 -

DELIMITER $$

CREATE TRIGGER trigger1
BEFORE DELETE
ON table1
FOR EACH ROW
BEGIN
  IF OLD.id = 1 THEN -- Abort when trying to remove this record
    CALL cannot_delete_error; -- raise an error to prevent deleting from the table
  END IF;
END
$$

DELIMITER ;

【讨论】:

  • MySQL 添加了 SIGNAL 命令来引发错误。我认为它是在这个答案之后添加的。如果有人感兴趣:dev.mysql.com/doc/refman/5.5/en/signal.html
  • 很好的补充 @MathewFoscarini,我刚刚使用 Devart 的答案和您建议的 SIGNAL 命令重新回答了这个问题。
【解决方案3】:

嗯,错误消息非常清楚地告诉您:在 DELETE 触发器中没有 NEW。

  • 在 INSERT 触发器中,您可以使用 NEW.. 访问新值。
  • 在 UPDATE 触发器中,您可以使用 NEW. 访问新值,旧值使用 - 您猜对了 - OLD。
  • 在 DELETE 触发器中,您可以使用 OLD.. 访问旧值。

在 DELETE 中使用 NEW 毫无意义,就像在 INSERT 中使用 OLD 一样。

【讨论】:

    【解决方案4】:

    正如错误所说:删除时没有新变量。

    您只能在插入和更新时使用 new.id。请改用 old.id。

    SELECT * FROM DeviceCatalog WHERE DeviceCatalog.id=old.id;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-12-11
      • 1970-01-01
      • 2012-06-29
      • 1970-01-01
      • 1970-01-01
      • 2012-08-02
      相关资源
      最近更新 更多