외래 키 제약 조건에 사용 된 열을 변경할 수 없습니다.


111

테이블을 변경하려고 할 때이 오류가 발생했습니다.

Error Code: 1833. Cannot change column 'person_id': used in a foreign key constraint 'fk_fav_food_person_id' of table 'table.favorite_food'

다음은 성공적으로 실행 된 내 CREATE TABLE STATEMENT입니다.

CREATE TABLE favorite_food(
    person_id SMALLINT UNSIGNED,
    food VARCHAR(20),
    CONSTRAINT pk_favorite_food PRIMARY KEY(person_id,food),
    CONSTRAINT fk_fav_food_person_id FOREIGN KEY (person_id)
    REFERENCES person (person_id)
);

그런 다음이 문을 실행하려고 시도했지만 위의 오류가 발생했습니다.

ALTER TABLE person MODIFY person_id SMALLINT UNSIGNED AUTO_INCREMENT;

4
위의 예는 "Learning SQL, 2nd edition"책에서 발췌 한 것입니다. 저자 인 Alan Beaulieu가 수정하기를 바랍니다.
Dmitry

답변:


126

외래 키 필드 및 참조의 유형과 정의는 동일해야합니다. 이는 외래 키가 필드 유형 변경을 허용하지 않음을 의미합니다.

한 가지 해결책은 다음과 같습니다.

LOCK TABLES 
    favorite_food WRITE,
    person WRITE;

ALTER TABLE favorite_food
    DROP FOREIGN KEY fk_fav_food_person_id,
    MODIFY person_id SMALLINT UNSIGNED;

이제 person_id를 변경할 수 있습니다.

ALTER TABLE person MODIFY person_id SMALLINT UNSIGNED AUTO_INCREMENT;

외래 키 재생성

ALTER TABLE favorite_food
    ADD CONSTRAINT fk_fav_food_person_id FOREIGN KEY (person_id)
          REFERENCES person (person_id);

UNLOCK TABLES;

편집 : 댓글 덕분에 위의 잠금 추가

이 작업을 수행하는 동안 데이터베이스에 쓰기를 허용하지 않아야합니다. 그렇지 않으면 데이터 무결성 문제가 발생할 위험이 있습니다.

위에 쓰기 잠금을 추가했습니다.

자신의 ( INSERT, UPDATE, DELETE) 세션이 아닌 다른 세션의 모든 쓰기 쿼리는 시간 초과 또는 UNLOCK TABLES; 실행된다

http://dev.mysql.com/doc/refman/5.5/en/lock-tables.html

편집 2 : OP는 "외래 키 필드와 참조의 유형 및 정의가 동일해야합니다. 이는 외래 키가 필드 유형 변경을 허용하지 않음을 의미합니다."라는 줄에 대한 자세한 설명을 요청했습니다.

에서 FOREIGN KEY 제약 조건 : 5.5 참조 설명서의 MySQL

외래 키와 참조 된 키의 해당 열은 형식 변환없이 비교할 수 있도록 InnoDB 내부에서 유사한 내부 데이터 형식을 가져야합니다. 정수 유형의 크기와 부호는 동일해야합니다. 문자열 유형의 길이가 같을 필요는 없습니다. 바이너리가 아닌 (문자) 문자열 열의 경우 문자 집합과 데이터 정렬이 동일해야합니다.


1
이를 위해 트랜잭션을 사용하는 것을 잊지 마십시오. 그렇지 않으면 데이터베이스가 손상 될 수 있습니다.
Francois Bourgeois

5
불행히도 MySQL은 DDL 문에 대한 트랜잭션을 지원하지 않습니다. 열린 트랜잭션은 DDL 쿼리가 실행되기 전에 커밋됩니다. dev.mysql.com/doc/refman/5.5/en/implicit-commit.html
Michel Feldheim

2
외래 키를 다시 만드는 올바른 문은 다음과 같습니다. ALTER TALE favorite_food ADD CONTRAINT fk_fav_food_person_id FOREIGN KEY (person_id) REFERENCES person (id);
Felizardo 2016

1
person_id외래 키를 삭제 한 후 바로 수정하는 이유는 무엇 입니까? 이미 .txt 파일이기 때문에 변경하지 않은 것 같습니다 SMALLINT UNSIGNED.
Dennis Subachev

1
참조 테이블 구조 만 게시했기 때문에 그것이 무엇인지 알 수 없습니다. 이노 디비 바로 가기 만하고, SMALLINT 등 내부 형식으로 INT가
미셸 Feldheim

198

외래 키 검사를 끌 수 있습니다.

SET FOREIGN_KEY_CHECKS = 0;

/* DO WHAT YOU NEED HERE */

SET FOREIGN_KEY_CHECKS = 1;

프로덕션에 이것을 사용하지 말고 백업하십시오.


1
매우 안전하지 않은 솔루션 인 것 같습니다. 잠재적으로 데이터 무결성을 잃을 수 있습니까?
hrust

@Synaps-예, 삭제 / 업데이트 / 삽입하는 경우 가능합니다. 테이블을 수정하거나 db를 시드하는 경우 데이터 손실이 발생하지 않습니다. 반면에 데이터를 수동으로 검증해야합니다 (제약 조건을 제거했기 때문에)
Dementic

2
이 솔루션은 훌륭하며 데이터를 수정하기 전에 쓰기 잠금을 광고 한 다음 완료되면 잠금을 해제하는 경우 프로덕션에서 사용할 수 있습니다. SQL 파일을 사용하여 가능한 한 짧은 시간에 변경을 수행하는 것이 훨씬 좋습니다.
Francisco Zarabozo

빠르게 바뀌는 좋은 솔루션
Genaut

1
SET FOREIGN_KEY_CHECKS세션 범위에 따라 잠금이 필요하지 않습니다 (다른 세션에는 여전히 FK 제약 조건이 적용됨). 추가 / 제거를위한 그것의 완벽한 AUTO_INCREMENT(실제 열 데이터 유형을 변경하지 않습니다)하지만 하지 작동 당신이 합법적 인거야으로 (SMALLINT에서 INT로, 말) "진짜"의 열 데이터 유형을 변경하려고하면 150 FK constraint incorrectly formed때를 mysql은 이전 테이블을 새 테이블로 교체하려고합니다. 이 경우 수락 된 답변을 사용하십시오.
Xenos

-3

키 (기본 또는 외래)를 설정하면 키를 사용할 수있는 방법에 대한 제약 조건을 설정하게되며, 이로 인해 키로 수행 할 수있는 작업이 제한됩니다. 정말로 열을 변경하고 싶다면 제약 조건없이 테이블을 다시 만들 수 있습니다. 일반적으로 무언가를하고 싶지만 제약에 의해 차단 된 상황이있는 경우 제약이 아닌 원하는 작업을 변경하여 해결하는 것이 가장 좋습니다.


12
이다 와 같은 도움이되지 않는, 쓸모없는 대답!
ajmedway

3
@ajmedway 그런 다음 다른 사용자를 비난하지 않고 도움이 답을 쓸 수 있습니다
내가 가장 어리석은 사람이다

2
@IamtheMostStupidPerson 댓글없이 투표하는 것보다 훨씬 낫습니다. 적어도 댓글 작성자는 왜 반대표를 던 졌는지 짐작할 수 있습니다. "미안한 것보다 안전하다"와 같은 일반적인 대답은 유용하지 않습니다.
Csaba Toth
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.