부모 행을 삭제하거나 업데이트 할 수 없습니다. 외래 키 제약 조건이 실패합니다


170

할 때 :

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`);

답변:


108

있는 그대로, 광고주 테이블에서 행을 삭제해야 참조 테이블이 참조하는 작업 테이블에서 행을 삭제할 수 있습니다. 이:

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`);

외래 키 관계를 수정하면 삭제 문이 작동합니다.


3
첫 번째 줄에서 : "참조하는"대신 "참조하는"것이 아니라고 생각하십니까? 또는 참조 용어가 어떻게 작동해야하는지 오해 했습니까?
Abraham Philip

6
@AbrahamPhilip 나는 같은 생각을하고있었습니다. 광고주는 직업을 참조합니다.
keyser

270

간단한 방법은 외래 키 검사를 비활성화하는 것입니다. 변경 후 외래 키 확인을 다시 활성화하십시오.

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

171
이것은 문제에 대한 해결책이 아니라 바람직하지 않은 더러운 해결 방법입니다.
madfriend

20
내 경우에는 방금 큰 SQL 파일을 실행하고 마지막 문 중 하나가 실패했기 때문에 모든 테이블을 삭제하고 구문 오류를 수정 한 다음 다시 실행하여 원하는 것을 정확하게 만들었습니다.
ekerner

1
이 작업을 수행하려는 경우 모든 제약 조건을 제거하지 않는 이유는 무엇입니까?
Sablefoste

1
다음과 같은 작업을 수행 할 때 유용합니다.REPLACE INTO tab_with_constraint ...
Maciek Łoziński

5
이 답변을 찬성하는 유일한 이유는 코드가 당신에게 고함을 멈추고 작성중인 코드를 이해하지 않고 스파게티에 더 깊이 들어가기를 원하기 때문입니다. 우선 외래 키를 갖는 이유는 참조 무결성을 강화하기위한 것입니다. 코드 종료를 위해 비활성화해야하는 경우 외래 키를 비활성화하는 대신 다시 생각해야 할 수 있습니다.
cytinus

38

현재 (결함이있는) 디자인에서 참조하는 작업 테이블에서 행을 삭제 하기 전에 광고주 테이블 에서 행을 삭제해야합니다.

또는 부모 테이블을 삭제하면 자식 테이블의 행이 자동으로 삭제되도록 외래 키를 설정할 수 있습니다. 이를 계단식 삭제라고합니다. 다음과 같이 보입니다 :

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

다른 사람들이 이미 지적했듯이 광고주 테이블에는 실제로 기본 키가 있고 작업 테이블에는 외래 키가 있기 때문에 외래 키가 다른 방향으로 가야한다고 생각합니다. 다음과 같이 다시 작성합니다.

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

계단식 삭제는 필요하지 않습니다.


18

테이블을 삭제하려면 단일 쿼리에서 다음 쿼리를 실행해야합니다.

SET FOREIGN_KEY_CHECKS = 0; DROP TABLE table_name;


13

@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

6

외래 키가 거꾸로 된 것 같습니다. 시험:

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

5

동일한 campaign_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 CASCADE;

외래 키 제약 조건 확인



2

데이터베이스를 만들거나 테이블을 만들 때

맨 위 스크립트에서 해당 행을 추가하여 데이터베이스 또는 테이블을 작성하십시오.

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

행운을 빕니다!


2

이 대안은 내가 사용한 것입니다 : 외래 키를 NULL로 허용 한 다음 ON DELETE SET NULL 을 선택하십시오 .

개인적으로 불필요한 합병증을 피하기 위해 " ON UPDATE CASCADE "와 " ON DELETE SET NULL "을 둘 다 사용하는 것을 선호 하지만 설정시 다른 접근 방식을 원할 수도 있습니다. 또한 NULL의 외래 키 값은 정확히 무슨 일이 있었는지 알 수 없으므로 나중에 합병증을 유발할 수 있습니다. 따라서이 변경은 응용 프로그램 코드 작동 방식과 밀접한 관련이 있어야합니다.

도움이 되었기를 바랍니다.


2

나는이 문제 있었다 laravel 마이그레이션 너무
아래에있는 드롭 테이블의 순서 () 메소드가 중요합니까를

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

작동하지 않을 수 있지만 주문을 변경하면 작동합니다.

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

1

가능한 빨리 클라이언트를 지원해야하고 액세스 할 수없는 경우

FOREIGN_KEY_CHECKS

데이터 무결성을 비활성화 할 수 있습니다.

1) 외래 키 삭제

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

2) SQL 또는 API를 통해 삭제 작업을 활성화하십시오.

3) 외래 키를 다시 스키마에 추가

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

그러나이 방법은 핫픽스이므로 사용자가 직접 위험을 감수해야합니다. 이러한 접근 방식의 주요 결함은 나중에 데이터 무결성을 수동으로 유지하는 것이 필요하기 때문입니다.


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 ;

0

이 오류의 주요 문제점 은 FK 실패 가 포함 된 테이블Error Code: 1451. Cannot delete or update a parent row: a foreign key constraint fails 을 알려주지 않으므로 충돌을 해결하기가 어렵다는 것입니다.

MySQL 또는 이와 유사한 것을 사용하는 경우 데이터베이스에 대한 ER 다이어그램 을 작성할 수 있음을 발견 한 후 오류를 유발하는 충돌을 검토하고 안전하게 제거 할 수 있습니다.

  1. MySQL 워크 벤치 사용
  2. 데이터베이스-> 리버스 엔지니어링을 클릭하십시오.
  3. 올바른 것을 선택하십시오 connection
  4. 끝날 때까지 다음, 선택 기억 databasetables그 검사 필요
  5. 이제 ER 다이어그램이 있습니다. FK 충돌이있는 테이블을 확인할 수 있습니다

0

기본적으로 이러한 유형의 오류의 원인은 결국 기본 키 (루트 테이블)가있는 터플을 삭제하려고 시도하고 기본 키가 자식 테이블에서 외래 키로 사용되기 때문입니다. 이 시나리오에서 상위 테이블 데이터를 삭제하려면 외래 키가 사용되는 하위 테이블 데이터를 제거해야합니다. 감사


0

이것은 나에게도 일어 났으며 다른 테이블의 종속성과 참조로 인해 항목을 제거 할 수 없었습니다. 내가 한 것은 테이블에 삭제 열 (부울 유형)을 추가하는 것입니다. 해당 필드의 값은 항목의 삭제 표시 여부를 보여줍니다. 삭제 표시가 있으면 가져 오거나 사용하지 마십시오. 그렇지 않으면 사용하십시오.


-1

DELETE CASCADE를 시도해야 할 수도 있습니다.


34
문제를 이해하지 않고 계단식 삭제 (데이터 삭제)를 맹목적으로 추가하는 것은 할 수있는 최악의 일입니다.
Tom H
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.