无法删除或更新父行:外键约束失败

时间:2009-12-15 06:09:53

标签: mysql sql

做的时候:

DELETE FROM `jobs` WHERE `job_id` =1 LIMIT 1 

错误:

#1451 - Cannot delete or update a parent row: a foreign key constraint fails 
(paymesomething.advertisers, CONSTRAINT advertisers_ibfk_1 FOREIGN KEY 
(advertiser_id) REFERENCES jobs (advertiser_id))

以下是我的表格:

CREATE TABLE IF NOT EXISTS `advertisers` (
  `advertiser_id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(255) NOT NULL,
  `password` char(32) NOT NULL,
  `email` varchar(128) NOT NULL,
  `address` varchar(255) NOT NULL,
  `phone` varchar(255) NOT NULL,
  `fax` varchar(255) NOT NULL,
  `session_token` char(30) NOT NULL,
  PRIMARY KEY (`advertiser_id`),
  UNIQUE KEY `email` (`email`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 AUTO_INCREMENT=2 ;


INSERT INTO `advertisers` (`advertiser_id`, `name`, `password`, `email`, `address`, `phone`, `fax`, `session_token`) VALUES
(1, 'TEST COMPANY', '', '', '', '', '', '');

CREATE TABLE IF NOT EXISTS `jobs` (
  `job_id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `advertiser_id` int(11) unsigned NOT NULL,
  `name` varchar(255) NOT NULL,
  `shortdesc` varchar(255) NOT NULL,
  `longdesc` text NOT NULL,
  `address` varchar(255) NOT NULL,
  `time_added` int(11) NOT NULL,
  `active` tinyint(1) NOT NULL,
  `moderated` tinyint(1) NOT NULL,
  PRIMARY KEY (`job_id`),
  KEY `advertiser_id` (`advertiser_id`,`active`,`moderated`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 AUTO_INCREMENT=2 ;


INSERT INTO `jobs` (`job_id`, `advertiser_id`, `name`, `shortdesc`, `longdesc`, `address`, `active`, `moderated`) VALUES
(1, 1, 'TEST', 'TESTTEST', 'TESTTESTES', '', 0, 0);

ALTER TABLE `advertisers`
  ADD CONSTRAINT `advertisers_ibfk_1` FOREIGN KEY (`advertiser_id`) REFERENCES `jobs` (`advertiser_id`);

18 个答案:

答案 0 :(得分:218)

简单的方法是禁用外键检查;进行更改,然后重新启用外键检查。

SET FOREIGN_KEY_CHECKS=0; -- to disable them
SET FOREIGN_KEY_CHECKS=1; -- to re-enable them

答案 1 :(得分:84)

按原样,您必须先删除广告商表中的行,然后才能删除它引用的作业表中的行。这样:

ALTER TABLE `advertisers`
  ADD CONSTRAINT `advertisers_ibfk_1` FOREIGN KEY (`advertiser_id`) 
      REFERENCES `jobs` (`advertiser_id`);

......实际上与应该是的相反。实际上,这意味着您必须在广告商之前在作业表中创建记录。所以你需要使用:

ALTER TABLE `jobs`
  ADD CONSTRAINT `advertisers_ibfk_1` FOREIGN KEY (`advertiser_id`) 
      REFERENCES `advertisers` (`advertiser_id`);

更正外键关系后,您的删除语句将起作用。

答案 2 :(得分:29)

在您当前(可能有缺陷的)设计下,您必须删除广告商表之前的行,您可以删除它引用的作业表中的行。

或者,您可以设置外键,以便父表中的删除会导致子表中的行自动删除。这称为级联删除。它看起来像这样:

ALTER TABLE `advertisers`
ADD CONSTRAINT `advertisers_ibfk_1`
FOREIGN KEY (`advertiser_id`) REFERENCES `jobs` (`advertiser_id`)
ON DELETE CASCADE;

话虽如此,正如其他人已经指出的那样,你的外键感觉它应该反过来,因为广告商表真的包含主键而jobs表包含外键。我会像这样重写它:

ALTER TABLE `jobs`
ADD FOREIGN KEY (`advertiser_id`) REFERENCES `advertisers` (`advertiser_id`);

并不需要级联删除。

答案 3 :(得分:15)

如果要删除表,则应该一步执行以下查询

SET FOREIGN_KEY_CHECKS = 0; DROP TABLE table_name;

答案 4 :(得分:6)

我认为你的外键是倒退的。尝试:

ALTER TABLE 'jobs'
ADD CONSTRAINT `advertisers_ibfk_1` FOREIGN KEY (`advertiser_id`) REFERENCES `advertisers` (`advertiser_id`)

答案 5 :(得分:3)

禁用外键检查并进行更改,然后重新启用外键检查。

SET FOREIGN_KEY_CHECKS=0; -- to disable them
DELETE FROM `jobs` WHERE `job_id` = 1 LIMIT 1 
SET FOREIGN_KEY_CHECKS=1; -- to re-enable them

答案 6 :(得分:3)

如果有多个作业具有相同的advertiser_id,那么您的外键应为:

ALTER TABLE `jobs`
ADD CONSTRAINT `advertisers_ibfk_1` 
FOREIGN KEY (`advertiser_id`) 
REFERENCES `advertisers` (`advertiser_id`);

否则(如果在您的情况下反之亦然),如果您希望在删除作业中的行时自动删除广告客户中的行,请在外键中添加“ON DELETE CASCADE”选项

ALTER TABLE `advertisers`
ADD CONSTRAINT `advertisers_ibfk_1` 
FOREIGN KEY (`advertiser_id`) 
REFERENCES `jobs` (`advertiser_id`);
ON DELETE CASCASE

查看Foreign Key constraints

答案 7 :(得分:2)

创建数据库或创建表时

您应该在顶部脚本create database或table

中添加该行
SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=1;

现在要删除表中的记录?然后你写为

SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=1;
DELETE FROM `jobs` WHERE `job_id` =1 LIMIT 1
祝你好运!

答案 8 :(得分:2)

您需要按顺序删除它 表中存在依赖性

答案 9 :(得分:2)

我在 laravel migration 中也有这个问题 down()方法中drop table的顺序很重要

Schema::dropIfExists('groups');
Schema::dropIfExists('contact');

可能无效,但如果您更改订单,则可以正常工作。

Schema::dropIfExists('contact');
Schema::dropIfExists('groups');

答案 10 :(得分:2)

我尝试了@Alino Manzi提到的解决方案,但是在使用wpdb的WordPress相关表上,它对我不起作用。

然后我按如下所示修改了代码,

SET FOREIGN_KEY_CHECKS=OFF; //disabling foreign key

//run the queries which are giving foreign key errors

SET FOREIGN_KEY_CHECKS=ON; // enabling foreign key

答案 11 :(得分:1)

如果您需要尽快支持客户,并且无法访问

FOREIGN_KEY_CHECKS

以便可以禁用数据完整性:

1)删除外键

ALTER TABLE `advertisers` 
DROP FOREIGN KEY `advertisers_ibfk_1`;

2)激活你的删除操作thruogh sql或api

3)将外键添加回架构

ALTER TABLE `advertisers`
  ADD CONSTRAINT `advertisers_ibfk_1` FOREIGN KEY (`advertiser_id`) REFERENCES `jobs` (`advertiser_id`);
然而,这是一个热门修复,因此风险自负,因为这种方法的主要缺陷是之后需要手动保持数据完整性。

答案 12 :(得分:1)

我一直在使用的替代方法如何:允许外键 NULL ,然后选择 ON DELETE SET NULL

我个人更喜欢同时使用" ON UPDATE CASCADE "以及" ON DELETE SET NULL "为避免不必要的复杂情况,但在您的设置上,您可能需要采用不同的方法。此外,NULL和外键值可能会导致并发症,因为您不知道那里到底发生了什么。因此,此更改应与应用程序代码的工作方式密切相关。

希望这有帮助。

答案 13 :(得分:0)

也许你应该试试ON DELETE CASCADE

答案 14 :(得分:0)

您可以在删除作业之前创建一个触发器来删除引用的行。

    DELIMITER $$
    CREATE TRIGGER before_jobs_delete 
        BEFORE DELETE ON jobs
        FOR EACH ROW 
    BEGIN
        delete from advertisers where advertiser_id=OLD.advertiser_id;
    END$$
    DELIMITER ;

答案 15 :(得分:0)

此错误Error Code: 1451. Cannot delete or update a parent row: a foreign key constraint fails的主要问题在于,它不会让您知道哪个表包含 FK故障,因此很难解决冲突。

如果您使用MySQL或类似的软件,我发现您可以为数据库创建一个ER diagram,那么您可以检查并安全地删除任何引发错误的冲突。

  1. 使用MySQL工作台
  2. 单击数据库->逆向工程
  3. 选择正确的connection
  4. 接下来直到最后,记得选择需要检查的databasetables
  5. 现在您有了ER图,您可以看到哪个表存在FK冲突

答案 16 :(得分:0)

基本上, 这些类型的错误背后的原因是,您最终将尝试删除具有主键(根表)且该主键在子表中用作外键的tupple。 在这种情况下,为了删除父表数据,您必须删除子表数据(使用外键)。 谢谢

答案 17 :(得分:0)

这也发生在我身上,由于其他表的依赖性和引用,我无法删除该条目。我所做的是在表中添加了一个delete列(布尔类型)。该字段中的值显示该项目是否标记为删除。如果标记为删除,则不要获取/使用;否则,请使用它。