mysql - 在 MySql 中使用删除前触发器删除具有外键约束的行

标签 mysql sql triggers sql-delete delete-row

我有一个名为“estoque”的表,其外键引用另一个名为“produto”的表。然后我用几行填充了两个表。

这是我的表格:

    CREATE TABLE `produto` (
      `ID` int(11) NOT NULL AUTO_INCREMENT,
      `NOME` varchar(45) NOT NULL,
      `PRECO` float NOT NULL,
      PRIMARY KEY (`ID`),
      UNIQUE KEY `NOME_UNIQUE` (`NOME`)
    );

    CREATE TABLE `estoque` (
      `ID` int(11) NOT NULL AUTO_INCREMENT,
      `ID_PRODUTO` int(11) NOT NULL,
      `QUANTIDADE_PRODUTO` int(11) NOT NULL DEFAULT '0',
      PRIMARY KEY (`ID`),
      KEY `fk_Estoque_Produto1_idx` (`ID_PRODUTO`),
      CONSTRAINT `fk_Estoque_Produto1` FOREIGN KEY (`ID_PRODUTO`)
      REFERENCES `produto` (`ID`)
    );

我需要“estoque”来始终引用“产品”上的所有现有行。所以我在产品上创建了一个 AFTER INSERT 和 AFTER UPDATE 触发器:

    CREATE TRIGGER `cadastrar_novo_produto_no_estoque` 
    AFTER INSERT ON `produto` 
    FOR EACH ROW 
    INSERT IGNORE INTO estoque (ID_PRODUTO)
    VALUES (NEW.ID);

编辑:实际上,由于我无法更改“produto”上的“ID”列,因为它是主键,所以我认为我根本不需要 AFTER UPDATE 触发器。我说得对吗?

    CREATE TRIGGER `atualizar_novo_produto_no_estoque` 
    AFTER UPDATE ON `produto` 
    FOR EACH ROW 
    UPDATE estoque
        SET estoque.ID_PRODUTO = NEW.ID
        WHERE OLD.estoque.ID_PRODUTO = OLD.ID;

现在我需要一个触发器,这样每次我从“product”中删除一行时,它也会删除“estoque”中的相应行。

我试过这样创建一个:

    CREATE TRIGGER `deletar_produto_inexistente_no_estoque` 
    BEFORE DELETE ON `produto` 
    FOR EACH ROW DELETE FROM estoque
        WHERE estoque.ID_PRODUTO = ID;

但是每当我尝试从“produto”中删除一行时,我都会收到以下错误:

ERROR 1175: 1175: You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column. 
SQL Statement:
DELETE FROM `papelaria`.`produto` WHERE (`ID` = '6')

所以我尝试使用 OLD 关键字,如下所示:

        CREATE TRIGGER `deletar_produto_inexistente_no_estoque` 
        BEFORE DELETE ON `produto` 
        FOR EACH ROW DELETE FROM estoque
            WHERE OLD.estoque.ID_PRODUTO = OLD.ID;

然后我得到了这个错误:

ERROR 1054: 1054: Unknown column 'OLD.estoque.ID_PRODUTO' in 'where clause'
SQL Statement:
DELETE FROM `papelaria`.`produto` WHERE (`ID` = '6')

我错过了什么或做错了什么?

P.S.:不确定是否值得一提,但我对 sql 和一般编程还很陌生,所以如果您在回答时考虑到它,我将不胜感激(出于所有目的,假设我不知道关于任何事情的任何事情^^)

提前致谢!

最佳答案

您可以将 FK 修改为:

CONSTRAINT `fk_Estoque_Produto1`
    FOREIGN KEY (`ID_PRODUTO`) 
    REFERENCES `produto` (`ID`)
    ON DELETE CASCADE

然后您将不再需要删除前触发器,因为 estoque 表中的记录将被自动删除。

类似地,添加 ON UPDATE CASCADE 将解决您的“更新问题”,以防有人更新记录的 PK。

仍然不确定为什么要在 estoque 表中包含虚拟记录。

关于mysql - 在 MySql 中使用删除前触发器删除具有外键约束的行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56535179/

相关文章:

php - 实现 MySQL Transaction 生成主键并保存到 PHP 表单数据提交

mysql - 自动监控 MySQL 服务器的崩溃表

sql - Phantom LONG 数据类型导致我的 SQL 代码崩溃 - ORA-00997

mysql - Hibernate 不回滚触发器相关的更改

database - 触发器执行期间出现未知错误

php - 是否可以通过知道 PHP 中的用户名和密码(仅)来破解我的数据库

mysql - 了解 LEFT JOIN 内部在 MySQL 中的工作

php - 将 .csv 数据回显到文件

mysql - sql - 将列属性更改为唯一

MySQL 错误 1193 (HY00) : Uknown System variable 'loopCnt'