Mysql 错误1451:1451:无法删除或更新父行:外键约束失败
我一直在寻找这个错误,偶然发现了几个性质相同的问题, 但据我所知,他们似乎关心更新问题。我的原因是删除了一个条目 以下是我的桌子是如何组成的:Mysql 错误1451:1451:无法删除或更新父行:外键约束失败,mysql,database,rdbms,Mysql,Database,Rdbms,我一直在寻找这个错误,偶然发现了几个性质相同的问题, 但据我所知,他们似乎关心更新问题。我的原因是删除了一个条目 以下是我的桌子是如何组成的: CREATE TABLE `product` ( `product_id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT COMMENT 'represents unique identifier for every existing products', `code` varchar(20) NO
CREATE TABLE `product` (
`product_id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT COMMENT
'represents unique identifier for every existing products',
`code` varchar(20) NOT NULL,
`name` varchar(45) NOT NULL COMMENT 'description',
`price` decimal(11,4) NOT NULL,
`short_name` varchar(10) NOT NULL COMMENT
'name that can be used quickly to referenc or immediately know what is the product',
`count` bigint(19) unsigned NOT NULL DEFAULT '0',
`product_type_id` smallint(5) unsigned NOT NULL DEFAULT '0',
`is_active` bit(1) NOT NULL DEFAULT b'0',
PRIMARY KEY (`product_id`),
KEY `product_product_typeFK_idx` (`product_type_id`),
CONSTRAINT `product_product_typeFK` FOREIGN KEY (`product_type_id`) REFERENCES
`product_type` (`product_type_id`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8;
然后它还有一些附带的触发器
,可以插入一些数据:
USE `RFVPOS`;
DELIMITER $$
CREATE TRIGGER `Product_BDEL` BEFORE DELETE ON `product` FOR EACH ROW
BEGIN
INSERT INTO `product_audit`
(product_id,
code,
name,
short_name,
price,
count,
delete_user,
delete_date
)
values
(OLD.product_id,
OLD.code,
OLD.name,
OLD.short_name,
OLD.price,
OLD.count,
CURRENT_USER(),
NOW()
);
END
这也是“产品审计”的结构:
CREATE TABLE `product_audit` (
`product_audit_id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
`product_id` mediumint(8) unsigned NOT NULL,
`code` varchar(20) NOT NULL,
`name` varchar(45) NOT NULL,
`price` decimal(11,4) NOT NULL,
`short_name` varchar(10) NOT NULL,
`count` bigint(19) unsigned NOT NULL,
`delete_user` varchar(45) NOT NULL,
`delete_date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`product_audit_id`),
KEY `product_audit_productFK_idx` (`product_id`),
CONSTRAINT `product_audit_productFK` FOREIGN KEY (`product_id`) REFERENCES `product` (`product_id`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB AUTO_INCREMENT=17 DEFAULT CHARSET=utf8;
然后它会闪烁此错误:
错误1451:1451:无法删除或更新父行:外键约束失败
现在,以前让我困惑的是,没有其他表条目使用我在“product”表中删除的条目。这次删除应该进行得很顺利
因此,我尝试删除“product”表上的触发器,结果删除成功。这意味着错误在我的触发器上,您能帮我指出错误发生的确切位置(如果不在触发器上)和原因吗。您试图在
产品
表中删除的条目是另一个表的父项。这意味着,如果您试图从product
表中删除一个条目,其中product_id=1
,您必须确保首先删除引用此条目的所有条目
假设您有一个名为user
+--------+-------+--------+
| UserID | Name | Gender |
+--------+-------+--------+
| 1 | Jason | Male |
+--------+-------+--------+
| 2 | Sara | Female |
+--------+-------+--------+
| 3 | John | Male |
+--------+-------+--------+
您有一个表user\u address
,它引用user
表,其中user\u id
为外键
+-----------+-----------+--------+
| AddressID | Address | UserID |
+-----------+-----------+--------+
| 1 | Address A | 1 |
+-----------+-----------+--------+
| 2 | Address B | 1 |
+-----------+-----------+--------+
| 3 | Address C | 2 |
+-----------+-----------+--------+
现在,如果要对user
运行删除查询,如下所示:
delete from user where userID=1;
您必须确保删除它的所有子项(依赖项),在这个游戏中是地址A
和地址B
,然后删除触发器将插入产品审计的产品。如果product\u audit
中的product\u id
列是product
的外键,则不能再从product
中删除此行,因为它是product\u audit
中新创建行的父级
尝试从产品\u audit
中删除外键约束
由于您没有显示产品\u audit
的表定义,因此上述内容只是猜测。(也就是说,在撰写本文时。但我的猜测是正确的!)您可以通过运行以下查询来检查product\u id
是否在任何其他表中用作外键
SELECT constraint_name, table_name
FROM information_schema.table_constraints
WHERE constraint_type = 'FOREIGN KEY'
AND table_schema = DATABASE()
AND constraint_name LIKE '%product_id%'
ORDER BY constraint_name;`
“现在,以前让我困惑的是,没有其他表条目使用我在‘产品’表上删除的条目。这次删除应该进行得很顺利。”-正如我前面所说。这和你说的一样吗?你说什么是其他桌子的家长?你的意思是,外键是其他表的吗?这个答案很清楚。顺便问一下,在产品审核中设置约束是否可取?我的意思是,任何捕获已删除条目的表?您试图实现的是“软删除”之类的。因此,您希望从数据库中删除条目,但不是完全删除—您希望备份它们,对吗?在这种情况下,我不会将这些条目移动到另一个表中,但我会在product
表中创建另一列,名为deleted
。默认值为0/false。无论何时,只要将deleted设置为1/true,就可以从product
中删除一行。每当您从product
中选择时,请将WHERE deleted=0
添加到查询中。您还可以使用产品表.Yep中的WHERE
语句创建一个视图。我之所以想把它放在另一张桌子上,是为了避免桌子变大,影响性能?我不太确定我说了什么。如果您担心表会增长太多,您也可以将删除的列更改为时间戳,并允许NULL
值NULL
表示此列尚未删除。删除时,将列设置为NOW()
。然后,您可以每隔一段时间从表中完全删除行,这些行在某个时间之前(即一个多月前或类似的时间)已被删除。您仍然可以恢复最近删除的行,但您的表不会无限期增长。我建议您创建另一个问题,在该问题中说明软删除的问题。提及你已经考虑过的不同方法,并陈述你在每种方法中看到的缺点,并就如何最好地实现你的目标征求建议(明确地指定它们)!