在MySql中使用Before Delete触发器删除具有外键约束的行

在MySql中使用Before Delete触发器删除具有外键约束的行,mysql,sql,triggers,sql-delete,delete-row,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 `NO

我有一个名为“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'始终引用'product'上的所有现有行。所以我在产品上创建了一个后插入和一个后更新触发器:

    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”列,所以我认为我根本不需要更新后触发器。我说得对吗

    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')
因此,我尝试使用旧关键字,例如:

        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')
我错过了什么或做错了什么

附言:我不确定这是否值得一提,但我对sql和编程基本上还是比较陌生的,所以如果您在回答时考虑到这一点,我将不胜感激(出于所有目的,假设我对任何事情都不了解^^)


提前谢谢你

您可以将FK修改为:

CONSTRAINT `fk_Estoque_Produto1`
    FOREIGN KEY (`ID_PRODUTO`) 
    REFERENCES `produto` (`ID`)
    ON DELETE CASCADE
然后您将不再需要before delete触发器,因为
estoque
表中的记录将被自动删除

类似地,在更新级联中添加
将解决您的“更新问题”,以防有人更新记录的PK


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

您能否澄清一下,为什么是1。您需要estoque表2中的虚拟记录。为什么在删除produto中的记录时,不能使用“删除级联”上的FK删除estoque表中的记录?谢谢。它工作得很好。我无法更改外键,所以我不得不删除它,并创建一个新的外键,同时使用级联删除和级联更新。我以前没有这么做的原因很简单,因为我不知道级联是什么,哈哈,就像我说的,我对sql和编程都是新手。谢谢你给我指明了正确的方向!另外,什么是虚拟记录?这是否意味着不必要的数据?为了澄清,
produto
是一个跟踪所有现有产品的表格
estoque
是一个库存表,只是为了让我知道我有多少产品可供未来销售。你是说我可能应该删除
estoque
表,只需在
product
表中添加一个
quantity
列?这是一种更好、更干净的数据库设计方法吗?在dummy record下,我指的是添加新产品时从触发器添加的estoque表中的记录。我不会这样做。estoque表中没有信息==产品不可用。然而,您的真实应用程序可能会预期返回零,因此您需要更改“get”查询或像现在一样拥有虚拟记录。我不知道什么对你们更合适:像你们做的那个样将数量单独放在一张表中,或者作为产品列。我更喜欢将库存信息不放在商品表中。如果问题解决了,请随意“接受”答案。