가짜 외래 키 제약 조건 실패


110

이 오류 메시지가 나타납니다.

40 행의 오류 1217 (23000) : 상위 행을 삭제하거나 업데이트 할 수 없습니다. 외래 키 제약 조건이 실패합니다.

... 테이블을 삭제하려고 할 때 :

DROP TABLE IF EXISTS `area`;

... 다음과 같이 정의됩니다.

CREATE TABLE `area` (
  `area_id` char(3) COLLATE utf8_spanish_ci NOT NULL,
  `nombre_area` varchar(30) COLLATE utf8_spanish_ci NOT NULL,
  `descripcion_area` varchar(100) COLLATE utf8_spanish_ci NOT NULL,
  PRIMARY KEY (`area_id`),
  UNIQUE KEY `nombre_area_UNIQUE` (`nombre_area`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_spanish_ci;

재미있는 점은 에 대한 외래 키가있는 스키마의 다른 모든 테이블이미 삭제 했다는 것입니다 area. 실제로 데이터베이스는 area테이블을 제외하고 비어 있습니다.

데이터베이스에 다른 개체가 없으면 어떻게 자식 행을 가질 수 있습니까? 내가 아는 한 InnoDB는 다른 스키마의 외래 키를 허용하지 않습니다.

( RENAME TABLE area TO something_else명령을 실행할 수도 있습니다 :-?)


테이블이 다른 스키마에서 참조 무결성 관계의 일부일 수 있습니까?
Raj More

앱의 다른 사본이 있으므로 항상 가능합니다. 그러나 내가 사용하는 구문은 기본적으로 CONSTRAINT fk_servicio_area1 FOREIGN KEY (area_id) REFERENCES area (area_id)즉, 테이블 참조에 스키마 이름이 없습니다.
Álvaro González

답변:


101

두 가지 가능성 :

  1. FK 참조가있는 다른 스키마 (mysql 용어로 "데이터베이스") 내에 테이블이 있습니다.
  2. innodb 내부 데이터 사전이 mysql 사전과 동기화되지 않았습니다.

드롭이 실패한 후 "SHOW ENGINE INNODB STATUS"를 수행하여 어떤 테이블 (어쨌든 그중 하나)을 확인할 수 있습니다.

후자의 경우라면 가능한 한 전체 서버를 덤프하고 복원 할 것입니다.

MySQL 5.1 이상은 오류 메시지에 FK가있는 테이블 이름을 제공합니다.


1
더 이상 문제를 재현 할 수 없습니다. 동기화되지 않은 사전이 그럴 가능성이있는 이유로 두드러집니다. 나는 그것을 하루 테스트하고 어떤 SHOW ENGINE INNODB STATUS보고서를 볼 것 입니다.
Álvaro González

3
이 답변에 감사드립니다! 우리가 삭제할 수없는 테이블을 여전히 참조하는 다 대다 테이블이 있었기 때문에 먼저 해당 테이블을 삭제해야했습니다.
Christian Oudard

5
SHOW ENGINE INNODB STATUS는 "LATEST FOREIGN KEY ERROR"아래에 마지막 외래 키 오류를 나열합니다. 타임 스탬프가 있습니다.
bbrame 2014

주제 테이블에 대한 참조 키가 여전히있는 테이블이있을 수 있습니다. 제 경우에는 이렇게요.
RT

많은 시간을 절약했습니다. "LATEST FOREIGN KEY ERROR"에서 db 삭제
Sand1512

121

주문형, 이제 대답으로 ...

MySQL Query Browser 또는 phpMyAdmin을 사용할 때 각 쿼리 ( bugs.mysql.com/bug.php?id=8280 ) 에 대해 새 연결이 열리는 것으로 나타나 므로 하나의 쿼리에 모든 drop 문을 작성해야합니다.

SET FOREIGN_KEY_CHECKS=0; 
DROP TABLE my_first_table_to_drop; 
DROP TABLE my_second_table_to_drop; 
SET FOREIGN_KEY_CHECKS=1; 

는 어디에서 SET FOREIGN_KEY_CHECKS=1추가 보안 조치의 역할을 ...


2
phpMyAdmin을 사용하여 덤프를 생성하는 경우 덤프 SET FOREIGN_KEY_CHECKS=0;시작 부분에 자동으로 추가 되는 "외래 키 검사 비활성화"옵션이 있습니다 .
Mike

phpMyAdmin이이 멋진 기능을 구현 한 것 같습니다. 이제 mysqlWorkbench가 동일한 작업을 수행하기를 기다리고 있습니다! :)
Karlis Rode

@CodeMed 참고로 MarkR의 대답은 말이되는 문제에 대한 설명을 제공하기 때문에 받아 들였습니다.하지만 이후 6 년 동안 동일한 문제에 직면하지 않았기 때문에 한 번도 확인하지 못했기 때문에 확인할 수 없었습니다. 이 답변과 이전 답변은 해결 방법을 제공하지만 질문 자체를 실제로 다루지는 않으며 선택해야하는 하나의 답변 만 수락 할 수 있기 때문입니다.
Álvaro González

1
경고 : 이것은 해결책이 아니라 게으른 사람의 해결 방법 일뿐입니다. (삭제 된 테이블을 가리키는 다른 테이블에서 레코드)이 사용 후에는 치명적으로 일관성 (나누기 외래 키 매달려 경험하게 될 것입니다 C 에서 ACID 데이터베이스의를) 및 응용 프로그램이 사방에 예외를 던져 시작됩니다. 경고를 받았습니다.
bekce

bekce의 경고를 이해하고주의를 기울여야한다고 확신하지만이 솔루션은 문제가있는 외래 키 제약 조건이있는 테이블을 가리키는 모든 테이블을 삭제한다고 확신하는 상황에서 저에게 효과적이었습니다.
user1147171 apr

47

외래 키 검사 비활성화

SET FOREIGN_KEY_CHECKS=0

62
올바른 명령이 표시되고 SET FOREIGN_KEY_CHECKS=0오류 메시지를 수정합니다. 이것이 필요한 이유에 대해 알고 있습니까? 테이블이 사라진 후에도 외래 키가 캐시됩니까?
Álvaro González

1
솔직히 말해서 왜 그런 문제가 발생하는지 모르겠지만 큰 변경이나 업데이트를 할 때마다 키 검사를 비활성화하십시오. 여러 번 나에게 일어 났고 며칠 동안 잠을 자지 못했습니다.
Flakron Bytyqi

55
SET FOREIGN_KEY_CHECKS=1;완료 한 후에 확인하십시오 !
pedro_sland 2010

5
MySQL Query Browser 또는 phpMyAdmin을 사용할 때 각 쿼리 ( bugs.mysql.com/bug.php?id=8280 ) 에 대해 새 연결이 열리는 것으로 나타나 므로 하나의 쿼리에 모든 drop 문을 작성해야합니다. SET FOREIGN_KEY_CHECKS=0; DROP TABLE my_first_table_to_drop; DROP TABLE my_second_table_to_drop; SET FOREIGN_KEY_CHECKS=1; SET FOREIGN_KEY_CHECKS = 1이 추가 보안 조치로 사용되는 경우 ...
Karlis Rode 2013-07-02

1
phpMyAdmin에 대한 의견은 @KarlisRode, Bravo입니다. 대답으로 넣으면 +1하겠습니다.
Sablefoste 2013 년

28

에서 이 블로그 :

일시적으로 외래 키 검사를 비활성화 할 수 있습니다.

SET FOREIGN_KEY_CHECKS=0;

엉망이 된 후에는 복원하십시오.

SET FOREIGN_KEY_CHECKS=1;

내가 지역에서 개발할 때 좋은 대답 :)
Adelin

유효한 해결 방법이지만 (작동하는지 확인할 수 있음) 링크 된 블로그 항목은이 질문의 시나리오 (한 테이블에 대해 이미 비어있는 데이터베이스)에 대해 실제로 이야기하지 않습니다.
Álvaro González

6

바라건대 그 일

SET foreign_key_checks = 0; 드롭 테이블 table name; SET foreign_key_checks = 1;


예, 작동, 여러 번으로 언급 된되기 전에 ;-)
알바로 곤잘레스

1

Rails에서는 다음을 사용하여 다음을 수행 할 수 있습니다 rails console.

connection = ActiveRecord::Base.connection
connection.execute("SET FOREIGN_KEY_CHECKS=0;")

0

이전에이 테이블로 작업 할 때 오류가 발생했을 수 있습니다. 테이블 이름을 바꾸고 다시 제거 할 수 있습니다.

ALTER TABLE `area` RENAME TO `area2`;
DROP TABLE IF EXISTS `area2`;

0

나는 쉬운 해결책을 찾았고, 데이터베이스를 내보내고, 텍스트 편집기에서 편집하려는 것을 편집 한 다음 가져옵니다. 끝난


4
이것은 실제로 발생해서는 안되는 흥미로운 솔루션입니다. 대신 변경이 필요한 모든 것은 DBMS를 통해 이루어져야합니다. 텍스트 편집기에서 데이터베이스 덤프를 편집하는 것은 문제를 해결하는 방법처럼 보입니다.
Brandon Anzaldi 2016 년

1
나는 당신이 무엇을 좋아하는지 정말로 이해하지 못합니다. 데이터베이스를 덤프하고 CREATE TABLE코드를 제거하고 덤프를 다시로드해도 MySQL이 테이블을 제거하지는 않습니다. 그리고 새 데이터베이스에서 덤프를 복원하려는 경우 ... 나와 같은 모든 테이블을 지우고 싶다면 새로 생성 된 데이터베이스가 이미 비어있을 것입니다. 일부 테이블을 유지하려면 SET FOREIGN_KEY_CHECKS=0여기에서 언급 한 해결 방법이 잘 작동하고 더 간단합니다. 데이터의 새 복사본에 동기화되지 않은 데이터 사전이 없을 수 있으므로 어쨌든 덤프를 편집 할 필요가 없습니다.
알바로 곤잘레스

-1

상위 행을 삭제하거나 업데이트 할 수 없습니다. 외래 키 제약 조건이 실패합니다 ( table1. user_role, CONSTRAINT FK143BF46A8dsfsfds@#5A6BD60FOREIGN KEY ( user_id) REFERENCES user( id)).

두 가지 간단한 단계로 내가 한 일. 먼저 자식 테이블에서 자식 행을 삭제합니다.

mysql> delete from table2 where role_id = 2 && user_id = 20;

쿼리 OK, 1 개 행 영향 (0.10 초)

두 번째 단계는 부모 삭제로

id = 20 인 table1에서 삭제;

쿼리 OK, 1 개 행 영향 (0.12 초)

이것으로 나는 자식 삭제 다음 부모 삭제를 의미하는 문제를 해결합니다.

나는 당신이 그것을 얻길 바랍니다. :)


질문을 다시 읽으십시오. 존재하지 않는 테이블은 제거 할 수 없습니다.
Álvaro González

이 시나리오에서는 외래 키 제약 조건을 제거한 다음 테이블 삭제를 시도 할 수 있습니다. 다음과 같은 외래 키를
삭제할
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.