MySQL 오류 1452-자식 행을 추가하거나 업데이트 할 수 없음 : 외래 키 제약 조건이 실패 함


237

이상한 문제가 있습니다. 다른 테이블을 참조하는 테이블에 외래 키를 추가하려고하는데 어떤 이유로 실패합니다. MySQL에 대한 나의 제한된 지식으로, 아마도 의심의 여지가있는 유일한 것은 내가 참조하려고하는 것을 참조하는 다른 테이블에 외래 키가 있다는 것입니다.

SHOW CREATE TABLE두 테이블 모두 에서 쿼리를 수행 sourcecodes_tags했으며 외래 키 sourcecodes가있는 테이블이며 참조 테이블입니다.

CREATE TABLE `sourcecodes` (
 `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
 `user_id` int(11) unsigned NOT NULL,
 `language_id` int(11) unsigned NOT NULL,
 `category_id` int(11) unsigned NOT NULL,
 `title` varchar(40) CHARACTER SET utf8 NOT NULL,
 `description` text CHARACTER SET utf8 NOT NULL,
 `views` int(11) unsigned NOT NULL,
 `downloads` int(11) unsigned NOT NULL,
 `time_posted` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
 PRIMARY KEY (`id`),
 KEY `user_id` (`user_id`),
 KEY `language_id` (`language_id`),
 KEY `category_id` (`category_id`),
 CONSTRAINT `sourcecodes_ibfk_3` FOREIGN KEY (`language_id`) REFERENCES `languages` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
 CONSTRAINT `sourcecodes_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
 CONSTRAINT `sourcecodes_ibfk_2` FOREIGN KEY (`category_id`) REFERENCES `categories` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=latin1

CREATE TABLE `sourcecodes_tags` (
 `sourcecode_id` int(11) unsigned NOT NULL,
 `tag_id` int(11) unsigned NOT NULL,
 KEY `sourcecode_id` (`sourcecode_id`),
 KEY `tag_id` (`tag_id`),
 CONSTRAINT `sourcecodes_tags_ibfk_1` FOREIGN KEY (`tag_id`) REFERENCES `tags` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=latin1

이것은 오류를 생성하는 코드입니다.

ALTER TABLE sourcecodes_tags ADD FOREIGN KEY (sourcecode_id) REFERENCES sourcecodes (id) ON DELETE CASCADE ON UPDATE CASCADE

2
삽입 / 업데이트 명령을 게시하여 오류가 발생할 수 있습니까?
Zed

64
외래 키를 추가 할 때 테이블이 비어 있습니까?
Zed

12
이 쿼리를 실행하여 실제 ID가 아닌 sourcecode_id가 있는지 확인하십시오. SELECT sourcecode_id FROM sourcecodes_tags WHERE sourcecode_id NOT IN (SELECT id FROM sourcecodes AS tmp);
Zed

11
감사합니다 Zed, 그것은 테이블 중 하나에 데이터가있는 문제였습니다. 지금 생각하면 존재하지 않는 항목을 참조하는 것이 있었기 때문에 실패했다는 것이 합리적이지만 결코 추측하지 못했습니다. 감사!
Zim

2
테이블이 비어 있으면 왜 실패합니까?
theblackpearl

답변:


226

sourcecodes_tags테이블에 sourcecode_id더 이상 존재하지 않는 값이 테이블에 포함되어 있을 가능성이 큽니다 sourcecodes. 먼저 제거해야합니다.

해당 ID를 찾을 수있는 쿼리는 다음과 같습니다.

SELECT DISTINCT sourcecode_id FROM 
   sourcecodes_tags tags LEFT JOIN sourcecodes sc ON tags.sourcecode_id=sc.id 
WHERE sc.id IS NULL;

UPDATE sourcecodes_tags SET sourcecode_id = NULL WHERE sourcecode_id NOT IN (SELECT id FROM sourcecodes)해당 ID를 제거하는 데 도움이됩니다. 또는 null에서 허용되지 않으면 sourcecode_id해당 행을 제거하거나 누락 된 값을 sourcecodes테이블에 추가 하십시오.
naXa

나는 똑같은 생각을했지만 SELECT Tchild.id FROM Tchild INNER JOIN Tmain ON Tmain.id = Tchild.fk_id WHERE Tmain.id IS NULL아무것도 돌려주지 않으므로 문제는 다른 곳입니다!?
Meloman

아아, 이것은 나에게 문제였다. 나는 UPDATE `homestead`.`automations` SET `deleted_at`=NULL WHERE deleted_at IS NOT NULL;외래 키를 전혀 사용하지 않는 을 실행하려고 했기 때문에 혼란 스러웠습니다. 그러나 연락처 테이블에 자동화 테이블에서 참조한 일부 레코드가 누락되어 "오류 코드 : 1452. 하위 행을 추가하거나 업데이트 할 수 없음 : 외래 키 제약 조건이 실패했습니다"라는 오류가 발생했습니다.
Ryan

99

내 MySQL 데이터베이스와 동일한 문제가 있었지만 마침내 나를 위해 일한 솔루션을 얻었습니다.
내 테이블에서는 mysql 관점에서 모든 것이 좋았습니다 (두 테이블 모두 InnoDB 엔진을 사용해야하고 각 열의 데이터 유형은 외래 키 제약 조건에 참여하는 동일한 유형이어야합니다).
내가 한 유일한 방법은 외래 키 검사를 비활성화하고 나중에 외래 키 작업을 수행 한 후 활성화했습니다.
내가 취한 단계 :

SET foreign_key_checks = 0;
alter table tblUsedDestination add constraint f_operatorId foreign key(iOperatorId) references tblOperators (iOperatorId); Query
OK, 8 rows affected (0.23 sec) Records: 8  Duplicates: 0  Warnings: 0
SET foreign_key_checks = 1;

49
foreign_key_checks는 이유가 있습니다. 제약 조건을 위반하여 외래 키를 추가 할 수없는 경우 먼저 데이터를 수정해야합니다. 검사를 끄고 키를 추가하면 일관성이없는 상태가됩니다. 외래 키 검사는 오버 헤드를 추가하고 사용하지 않으려면 myisam을 대신 사용하십시오.
cs_alumnus

5
@AbuSadatMohammedYasin 아닙니다. 질문은 "무엇이 진행되고 있는지"를 물었고이 답변은 단순히 그것을 설명하려고 시도하지 않습니다. cs_alumnus가 언급했듯이 더 큰 문제가 있습니다. 외래 키 처럼 다른 테이블의 다른 값을 참조 해야하는 모든 새로운 값은 아무것도 가리 키지 않아 일관성이없는 상태가됩니다. Cayetano의 짧고 효과적인 설명을 통해 제약 조건을 만들기 전에 업데이트해야 할 값을 찾을 수 있으므로 존재해야하는 값을 반환해야하는 쿼리에 놀라지 않을 것입니다!
팔걸이

55

NOT IN구속 조건이 구속 되는 위치를 찾는 데 사용하십시오 .

SELECT column FROM table WHERE column NOT IN 
(SELECT intended_foreign_key FROM another_table)

보다 구체적으로 :

SELECT sourcecode_id FROM sourcecodes_tags WHERE sourcecode_id NOT IN 
(SELECT id FROM sourcecodes)

편집 : INNOT IN연산자는 훨씬 빠르게보다 알려져있다 JOIN뿐만 아니라 훨씬 더 쉽게 구조, 반복에, 운영자.


1
따라서이를 올바르게 이해하면 이미 데이터가있는 테이블에 외래 키를 추가 할 수 있지만 부모 테이블의 각 행에 대해 자식 행이 존재하는 경우에만 가능합니까? 부모 테이블의 각 행에 대해 자식 행이 없으면 (쿼리에서 발견 한 것) 외래 키 스크립트가 실패합니다.
Vincent

@Vincent 부모 테이블에 의해 참조되는 테이블을 의미한다면, 그렇습니다! 따라서 Cayetano의 select를 사용하면 새 제약 조건 (FK)을 추가하기 전에 "자식"테이블에서 업데이트 / 제거해야하는 모든 행을 가져옵니다. 일단 그들이 "another_table"의 값을 가리키면 당신은 가야합니다!
팔걸이

23

테이블을 자른 다음 FK 제약 조건을 추가해보십시오 .

이 솔루션이 약간 어색하지만 100 % 작동한다는 것을 알고 있습니다. 그러나 이것이 문제를 해결하기위한 이상적인 솔루션은 아니지만 동의하는 데 동의합니다.


4
모든 것을자를 필요가 없습니다. "UPDATE sourcecodes_tags SET sourcecode_id = NULL 여기서 sourcecode_id NOT IN (소스 코드에서 id 선택)"이면 충분합니다. 또는 "sourcecode_id"에 널이 허용되지 않으면 해당 행을 제거하거나 누락 된 값을 "sourcecodes"테이블에 추가하십시오.
Torben

1
때로는 데이터가 자동 증가 PK를 증가 시키면 강제로 자릅니다.
François Breton

2
@ShankarDamodaran 테이블을 자르는 이유가 확실하지 않지만이 솔루션은 저에게 효과적이었습니다. 나는 관계를 작동시킬 수있었습니다 ... 감사합니다!
MizAkita

@MizAkita 다른 테이블에 해당 값이없는 행을 삭제하여 새 제약 조건을 만들 수 있기 때문에 작동합니다. Cayetano의 제안 과 같이 해당 행을 찾아 업데이트하거나 삭제하는 경우 다른 행을 삭제할 필요가 없습니다.
Armfoot

@ Amtfoot-외래 키로 테이블에 첫 번째 행을 추가 할 때이 문제가 발생했습니다. 그래서 검색 할 행이 없었습니다.
Krewetka

16

나 에게이 문제는 조금 다르고 확인하고 해결하기가 매우 쉽습니다.

테이블의 BOTH가 모두 InnoDB인지 확인해야합니다. 테이블 중 하나, 즉 참조 테이블이 MyISAM이면 제약 조건이 실패합니다.

    SHOW TABLE STATUS WHERE Name =  't1';

    ALTER TABLE t1 ENGINE=InnoDB;

14

child.column의 값이 이미 0이고 parent.id 값이 0이 아닌 경우 외래 키를 parent.id에서 child.column으로 설정할 때 발생합니다.

각 child.column이 NULL이거나 parent.id에 존재하는 값을 가지고 있는지 확인해야합니다.

그리고 지금 내가 쓴 진술을 읽었으므로, 그것이 그가 확인하고있는 것입니다.


14

나는 오늘 같은 문제가 있었다. 나는 네 가지를 테스트했는데 그중 일부는 이미 여기에 언급되어 있습니다.

  1. 자식 열에 부모 열에 존재하지 않는 값이 있습니까 (자식 열이 Null을 허용하는 경우 NULL 제외)

  2. 자식 및 부모 열의 데이터 형식이 동일합니까?

  3. 참조하는 상위 열에 색인이 있습니까? MySQL은 성능상의 이유로 이것을 필요로하는 것 같습니다 ( http://dev.mysql.com/doc/refman/5.5/en/create-table-foreign-keys.html )

  4. 그리고 이것은 나를 위해 그것을 해결했습니다. 두 테이블이 동일한 데이터 정렬을 가지고 있습니까?

UTF-8로 된 테이블 하나와 등거리에있는 다른 테이블이있었습니다. 작동하지 않았습니다. iso-table을 UTF-8 데이터 정렬로 변경 한 후 문제없이 제약 조건을 추가 할 수 있습니다. 필자의 경우 phpMyAdmin은 외래 키 제약 조건을 만들기위한 드롭 다운에서 아이 테이블을 아이 인코딩으로 표시하지 않았습니다.


7

MySQL의 외래 키 제약 조건을 설정할 수 없으므로 유효한 외래 키가 아닌 열 행 0에 잘못된 값이있는 것 같습니다.

다음 단계를 수행 할 수 있습니다.

  1. FK 제약 조건을 설정하려고 시도한 열을 삭제하십시오.

  2. 다시 추가하고 기본값을 NULL로 설정하십시오.

  3. 외래 키 제약 조건을 다시 설정하십시오.


5

같은 문제가 발생하여 테이블 행을 확인한 결과 외래 키를 정의하려는 필드 값과 일부 호환되지 않는 것으로 나타났습니다. 해당 값을 수정하고 다시 시도한 후 문제가 해결되었습니다.


4

테이블의 모든 데이터를 삭제하고 alter를 다시 실행합니다. 효과가있다. 눈부신 것은 아니지만 많은 시간을 절약 할 수 있습니다. 특히 고객 데이터가없는 애플리케이션은 아직 개발 단계에 있습니다.


4

이 시도

SET foreign_key_checks = 0;

ALTER TABLE sourcecodes_tags ADD FOREIGN KEY (sourcecode_id) REFERENCES sourcecodes (id) ON DELETE CASCADE ON UPDATE CASCADE

SET foreign_key_checks = 1;

2

나는 세 번에 대해 똑같은 문제가있었습니다. 각각의 경우에 내 레코드 중 하나 이상이 새 외래 키를 따르지 않았기 때문입니다. 키 자체를 추가하기 전에 외래 키의 구문 제약 조건을 따르도록 기존 레코드를 업데이트 할 수 있습니다. 다음 예제는 일반적으로 문제점 레코드를 분리해야합니다.

SELECT * FROM (tablename)
    WHERE (candidate key) <> (proposed foreign key value) 
        AND (candidate key) <> (next proposed foreign key value)

AND (candidate key) <> (next proposed foreign key value)외래 키의 각 값에 대해 쿼리 내에서 반복 하십시오.

레코드 수가 많으면 어려울 수 있지만 테이블이 상당히 작 으면 너무 오래 걸리지 않습니다. 나는 SQL 구문에서 놀랍지 않지만 항상 문제를 해결했습니다.


2

테이블 데이터를 모두 비우고 명령을 실행하십시오. 작동합니다.


VHanded는 3 년 전에 같은 대답을했습니다. 테이블에 중요한 데이터가 없었 으면 좋겠습니다.
xlecoustillier


1

이 솔루션을 준비하고 있었고이 예제가 도움이 될 수 있습니다.

내 데이터베이스에는 기본 키가있는 두 개의 테이블 (이메일 및 credit_card)이 있습니다. 다른 테이블 (클라이언트)은이 테이블 ID를 외래 키라고합니다. 이메일을 클라이언트 데이터와 분리해야 할 이유가 있습니다.

먼저 참조 된 테이블 (이메일, credit_card)의 행 데이터를 삽입 한 다음 각각에 대한 ID를 얻습니다.이 ID는 세 번째 테이블 (클라이언트)에 필요합니다.

참조 된 테이블에 행을 먼저 삽입하지 않으면 MySQL은 외래 키를 참조하는 세 번째 테이블에 새 행을 삽입 할 때 대응 할 수 없습니다.

참조 된 테이블에 대해 참조 된 행을 먼저 삽입하면 외래 키를 참조하는 행은 오류가 발생하지 않습니다.

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


mysql> 이메일 (이메일) 값에 삽입 ( 'xxx@yyy.com'); mysql> ndtc (ndtc, year, month) 값에 삽입 ( '1111222233334444', '2000', '01'); mysql> 클라이언트 (nombres, apellidos, telefono, idNDTC, idEmail) 값에 삽입 ( 'myname', 'myapp', '5555555555', 1,1);
SubstanceMX

1

값이 다른 테이블에 있는지 확인하십시오. 그렇지 않으면 할당 된 해당 열에이 오류가 발생합니다.

따라서 할당 된 열이 다른 테이블의 행 ID에 할당 된 경우 테이블에 행이 있는지 확인하십시오. 그렇지 않으면이 오류가 나타납니다.


1

당신은이 exapmple을 시도 할 수 있습니다

 START TRANSACTION;
 SET foreign_key_checks = 0;
 ALTER TABLE `job_definers` ADD CONSTRAINT `job_cities_foreign` FOREIGN KEY 
 (`job_cities`) REFERENCES `drop_down_lists`(`id`) ON DELETE CASCADE ON UPDATE CASCADE;
 SET foreign_key_checks = 1;
 COMMIT;

참고 : phpmyadmin을 사용하는 경우 외래 키 검사 사용을 선택 취소하십시오.

여기에 이미지 설명을 입력하십시오

이 soloution이 문제를 해결하기를 바랍니다 :)


1

하나의 질문에 대답하면됩니다.

테이블에 이미 데이터가 저장되어 있습니까? (특히 표에는 외래 키가 포함되어 있습니다.)

대답이 예인 경우 모든 레코드를 삭제하는 것만으로도 테이블에 외래 키를 자유롭게 추가 할 수 있습니다.

삭제 명령 : 자식 (외래 키 테이블 포함)에서 부모 테이블로.

데이터 입력 후 외래 키를 추가 할 수없는 이유는 테이블 불일치로 인한 것입니다. 이전 데이터로 채워진 테이블에서 새 외래 키를 어떻게 처리합니까?

대답이 아니오 인 경우 다른 지시 사항을 따르십시오.


0
UPDATE sourcecodes_tags
SET sourcecode_id = NULL
WHERE sourcecode_id NOT IN (
  SELECT id FROM sourcecodes);

해당 ID를 제거하는 데 도움이됩니다. 또는 null에서 허용되지 않으면 sourcecode_id해당 행을 제거하거나 누락 된 값을 sourcecodes테이블에 추가 하십시오.


0

외래 키 열 NULL대신 동일한 문제가 발생하여 해결책을 찾았습니다 NOT NULL. 다음은 쿼리입니다.

ALTER TABLE `db`.`table1`
ADD COLUMN `col_table2_fk` INT UNSIGNED NULL,
ADD INDEX `col_table2_fk_idx` (`col_table2_fk` ASC),
ADD CONSTRAINT `col_table2_fk1`
FOREIGN KEY (`col_table2_fk`)
REFERENCES `db`.`table2` (`table2_id`)
ON DELETE NO ACTION
ON UPDATE NO ACTION;

MySQL 은이 쿼리를 실행했습니다!


0

필자의 경우 동일한 구조의 새 테이블을 만들고 다른 테이블과의 관계를 만든 다음 문제가있는 이전 테이블에서 CSV로 데이터를 추출한 다음 CSV를 새 테이블로 가져오고 외래 키 검사를 비활성화했습니다. 가져 오기 중단을 비활성화하면 모든 데이터가 문제없이 새 테이블에 삽입 된 다음 이전 테이블이 삭제됩니다.

그것은 나를 위해 일했다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.