在MySql中使用Before Delete触发器删除具有外键约束的行
我有一个名为“estoque”的表,其中有一个外键引用另一个名为“produto”的表。然后我用几行填充了这两个表 这是我的桌子:在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
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”查询或像现在一样拥有虚拟记录。我不知道什么对你们更合适:像你们做的那个样将数量单独放在一张表中,或者作为产品列。我更喜欢将库存信息不放在商品表中。如果问题解决了,请随意“接受”答案。