MySQL中的触发“BEFORE DELETE”

时间:2017-07-22 00:09:34

标签: mysql sql database-trigger

删除记录会给我以下错误:

  

错误1442:1442:无法更新存储函数/触发器中的表'categoria',因为它已被调用此存储函数/触发器的语句使用。

这是我的触发器:

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”表中的所有记录新记录。

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

1 个答案:

答案 0 :(得分:0)

我想你要确保表中至少有一行代表'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)
);

当Contacto没有分类时,您引用'Sin Categoria'行。并且您希望确保没有人删除Categoria表中的那一行。

相反,我建议在Contacto中的行没有Categoria时使用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”的Categoria中的任何行。