在 MySQL“删除前”中触发

Posted

技术标签:

【中文标题】在 MySQL“删除前”中触发【英文标题】:Trigger in MySQL "BEFORE DELETE" 【发布时间】:2017-07-22 00:09:34 【问题描述】:

删除记录给我以下错误:

ERROR 1442: 1442: Can't update table 'categoria' in stored function/trigger 因为它已被调用此存储函数/触发器的语句使用。

这是我的触发器:

DROP trigger IF EXISTS tg_eliminarCategoria;
DELIMITER $$
CREATE TRIGGER tg_eliminarCategoria
    BEFORE DELETE ON Categoria
    FOR EACH ROW
BEGIN
    IF NOT EXISTS (SELECT * FROM Categoria WHERE nombreCategoria = 'Sin Categoria') THEN
        INSERT INTO Categoria (nombreCategoria) VALUES ('Sin Categoria');
    END IF;

    SET @idCategoria = (SELECT idCategoria FROM Categoria WHERE nombreCategoria = 'Sin Categoria');
    UPDATE Contacto SET idCategoria=@idCategoria WHERE idCategoria=OLD.idCategoria;
END$$
DELIMITER ;

触发器是通过从“Categoria”表中删除一条记录,检查是否存在“Sin Categoria”记录,如果不存在,则修改“Contacto”表中包含已删除记录的所有记录by 新纪录。

对不起我的英语,我还在学习。

【问题讨论】:

我同意 mysql。我不知道你想做什么。你能试着描述一下你想让触发器完成什么吗? 触发是通过从“Categoria”表中删除一条记录,检查是否有“Sin Categoria”记录,如果不存在则修改“Contacto”中的所有记录包含被新记录删除的记录的表。对不起我的英语,我还在学习。 【参考方案1】:

我猜你想确保表格中至少有一行'Sin Categoria'。

如果有人试图删除“Sin Categoria”,另一种方法是引发SIGNAL(就像一个例外)。

mysql> DROP trigger IF EXISTS tg_eliminarCategoria;
mysql> DELIMITER $$
mysql> CREATE TRIGGER tg_eliminarCategoria
    BEFORE DELETE ON Categoria
    FOR EACH ROW
BEGIN
    IF OLD.nombreCategoria = 'Sin Categoria' THEN
        SIGNAL SQLSTATE '45000'
            SET MESSAGE_TEXT = 'No debe eliminar la categoría especial: Sin Categoria';
    END IF;
END$$
mysql> DELIMITER ;

mysql> delete from Categoria;
ERROR 1644 (45000): No debe eliminar la categoría especial: Sin Categoria

不过,我想我有更好的建议。我猜您将它用于必须引用类别的外键,如下所示:

CREATE TABLE Contacto (
  idContacto INT AUTO_INCREMENT PRIMARY KEY,
  idCategoria INT NOT NULL,
  FOREIGN KEY (idCategoria) REFERENCES Categoria(idCategoria)
);

当联系人没有类别时,您引用“Sin Categoria”行。并且您要确保没有人删除 Categoria 表中的该行。

相反,我建议在 Contacto 中的行没有类别时使用 NULL。只需让 Contacto.idCategoria 允许 NULL:

CREATE TABLE Contacto (
  idContacto INT AUTO_INCREMENT PRIMARY KEY,
  idCategoria INT DEFAULT NULL,
  FOREIGN KEY (idCategoria) REFERENCES Categoria(idCategoria)
);

INSERT INTO Contacto
SET idContacto = 1234,
    idCategoria = NULL;

那么你不需要任何名为“Sin Categoria”的类别中的行。

【讨论】:

以上是关于在 MySQL“删除前”中触发的主要内容,如果未能解决你的问题,请参考以下文章

mysql--触发器

MYSQL 触发器

MySQL之触发器

MySQL之触发器

删除前的 Oracle 触发器

删除前删除相关记录触发postgresql