errno : 150을 제공하는 외래 키를 사용하여 MySQL 생성 테이블


98

다른 두 테이블의 기본 키를 참조하는 두 개의 외래 키를 사용하여 MySQL에서 테이블을 만들려고하는데 errno : 150 오류가 발생하고 테이블이 생성되지 않습니다.

다음은 세 테이블 모두에 대한 SQL입니다.

CREATE TABLE role_groups (
  `role_group_id` int(11) NOT NULL `AUTO_INCREMENT`,
  `name` varchar(20),
  `description` varchar(200),
  PRIMARY KEY (`role_group_id`)
) ENGINE=InnoDB;

CREATE TABLE IF NOT EXISTS `roles` (
  `role_id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(50),
  `description` varchar(200),
  PRIMARY KEY (`role_id`)
) ENGINE=InnoDB;

create table role_map (
  `role_map_id` int not null `auto_increment`,
  `role_id` int not null,
  `role_group_id` int not null,
  primary key(`role_map_id`),
  foreign key(`role_id`) references roles(`role_id`),
  foreign key(`role_group_id`) references role_groups(`role_group_id`)
) engine=InnoDB;

어떤 도움이라도 대단히 감사하겠습니다.


1
오류 출력을 게시하고 오류를 일으키는 명령 (3 개 중)을 알려주시겠습니까?
dave

4
백틱은 auto_increment무엇입니까? 그것은 유효하지 않습니다. Auto_increment는 식별자가 아니라 키워드입니다.
Bill Karwin

답변:


238

나는 ALTER TABLE ADD FOREIGN KEY.

한 시간 후 오류 150이 발생하지 않도록 다음 조건이 충족되어야합니다.

  1. 참조 할 외래 키를 정의하기 전에 Parent 테이블이 있어야합니다. 올바른 순서로 테이블을 정의해야합니다. 먼저 상위 테이블, 그 다음 하위 테이블. 두 테이블이 서로를 참조하는 경우 FK 제약 조건없이 하나의 테이블을 생성 한 다음 두 번째 테이블을 생성 한 다음를 사용하여 첫 번째 테이블에 FK 제약 조건을 추가해야합니다 ALTER TABLE.

  2. 두 테이블은 모두 외래 키 제약 조건을 지원해야합니다 ENGINE=InnoDB. 다른 스토리지 엔진은 외래 키 정의를 자동으로 무시하므로 오류나 경고를 반환하지 않지만 FK 제약 조건은 저장되지 않습니다.

  3. Parent 테이블에서 참조 된 열은 키의 가장 왼쪽 열이어야합니다. 상위의 키가 PRIMARY KEY또는 인 경우 가장 UNIQUE KEY좋습니다.

  4. FK 정의는 PK 정의와 동일한 순서로 PK 열을 참조해야합니다. 예를 들어 FK 인 경우 REFERENCES Parent(a,b,c)상위의 PK가 순서대로 열에 정의되어서는 안됩니다 (a,c,b).

  5. Parent 테이블의 PK 열은 Child 테이블의 FK 열과 동일한 데이터 유형이어야합니다. 예를 들어 상위 테이블의 PK 열이 UNSIGNEDUNSIGNED경우 하위 테이블 필드의 해당 열에 대해 정의해야 합니다.

    예외 : 문자열의 길이는 다를 수 있습니다. 예를 들어, VARCHAR(10)참조 할 수 VARCHAR(20)있거나 그 반대 일 수 있습니다 .

  6. 모든 문자열 유형 FK 열은 해당 PK 열과 동일한 문자 집합 및 데이터 정렬을 가져야합니다.

  7. 자식 테이블에 이미 데이터가있는 경우 FK 열의 모든 값은 부모 테이블 PK 열의 값과 일치해야합니다. 다음과 같은 쿼리로 확인하십시오.

    SELECT COUNT(*) FROM Child LEFT OUTER JOIN Parent ON Child.FK = Parent.PK 
    WHERE Parent.PK IS NULL;

    일치하지 않는 값을 0으로 반환해야합니다. 분명히이 쿼리는 일반적인 예입니다. 테이블 이름과 열 이름을 대체해야합니다.

  8. 부모 테이블과 자식 테이블 모두 테이블이 될 수 없습니다 TEMPORARY.

  9. 부모 테이블과 자식 테이블 모두 테이블이 될 수 없습니다 PARTITIONED.

  10. ON DELETE SET NULL옵션을 사용 하여 FK를 선언하는 경우 FK 열은 null을 허용해야합니다.

  11. 외래 키에 대한 제약 이름을 선언하는 경우 제약 조건이 정의 된 테이블뿐 아니라 전체 스키마에서 제약 조건 이름이 고유해야합니다. 두 테이블에는 이름이 같은 자체 제약 조건이 없을 수 있습니다.

  12. 새 FK를 만들려는 동일한 필드를 가리키는 다른 테이블에 다른 FK가 있고 형식이 잘못된 경우 (예 : 다른 데이터 정렬) 먼저 일관성을 유지해야합니다. 이는 SET FOREIGN_KEY_CHECKS = 0;실수로 정의 된 일관성없는 관계로 활용 되었던 과거 변경의 결과 일 수 있습니다 . 이러한 문제 FK를 식별하는 방법에 대한 지침은 아래 @andrewdotn의 답변을 참조하십시오.

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


4
추가 할 가치가있는 한 가지 더 : 상위 테이블의 PK가 둘 이상의 필드 인 경우 FK의 필드 순서는 PK의 순서와 동일해야합니다
Kip

26
이 같은 것들을 포함하고 int(11) unsigned NOT NULLint(11) NOT NULL.
Glen Solsberry

4
ALTER TABLE table_name ENGINE = InnoDB;
TolMera 2013

12
테이블이 ENGINE = MyISAM으로 정의 된 경우 외래 키 선언을 무시 하므로 errno 150을 생성하지 않습니다 . 자동차 엔진 문제를 피하는 가장 좋은 방법은 보트를 운전하는 것과 같습니다. :-)
Bill Karwin 2013 년

2
또한 CONSTRAINT의 ON DELETE규칙이 SET NULL외래 키가 실제로 NULL이 될 수 있는지 확인하십시오! 30 분 동안이 답변을 반복해서 읽으면서 내 테이블이 조건을 충족하지만 여전히 오류 150이 발생하는지 확인했습니다. 그런 다음 내 FK가 NOT NULL 필드로 규칙을 적용 할 수 없다는 것을 알았습니다.
Martin Joiner

62

MySQL의 일반 "errno 150"메시지 " 는 외래 키 제약 조건이 올바르게 형성되지 않았 음을 의미합니다 ." 이 페이지를 읽고 있는지 이미 알고있는 것처럼 일반적인 "errno : 150"오류 메시지는 실제로 도움이되지 않습니다. 하나:

실행 한 다음 출력에서 검색하여 실제 오류 메시지를 얻을 수 있습니다 .SHOW ENGINE INNODB STATUS;LATEST FOREIGN KEY ERROR

예를 들어 다음은 외래 키 제약 조건을 생성하려는 시도입니다.

CREATE TABLE t1
(id INTEGER);

CREATE TABLE t2
(t1_id INTEGER,
 CONSTRAINT FOREIGN KEY (t1_id) REFERENCES t1 (id));

오류와 함께 실패합니다 Can't create table 'test.t2' (errno: 150). 그것은 외래 키 문제라는 것 외에 다른 유용한 것을 아무에게도 말하지 않습니다. 그러나 실행 SHOW ENGINE INNODB STATUS;하면 다음 과 같이 표시됩니다.

------------------------
LATEST FOREIGN KEY ERROR
------------------------
130811 23:36:38 Error in foreign key constraint of table test/t2:
FOREIGN KEY (t1_id) REFERENCES t1 (id)):
Cannot find an index in the referenced table where the
referenced columns appear as the first columns, or column types
in the table and the referenced table do not match for constraint.

문제는 색인을 찾을 수 없다는 것입니다. SHOW INDEX FROM t1table에 대한 인덱스가 전혀 없음을 보여줍니다 t1. 예를 들어에 기본 키를 정의 t1하면 외래 키 제약 조건이 성공적으로 생성됩니다.


4
SHOW ENGINE INNODB STATUS거의 한 시간 동안 진단하려고했던 문제를 즉시 식별하는 데 도움이되었습니다. 감사.
jatrim 2014-08-29

필자의 경우, 이것은 내가 가리 키려는 동일한 필드를 FK 한 완전히 다른 테이블이 일관성이 없어서 새 테이블을 저장하지 않는다는 것을 나타냅니다. 이것이 SET FOREIGN_KEY_CHECKS = 0;잘못된 가져 오기 / 변경 중에 사용되었다고 가정합니다. 한 번 또는 다른. 큰 도움, 감사합니다.
oucil

25

제약 조건으로 연결하려는 두 필드의 속성이 정확히 동일한 지 확인하십시오.

종종 ID 열의 'unsigned'속성이 당신을 잡을 것입니다.

ALTER TABLE `dbname`.`tablename` CHANGE `fieldname` `fieldname` int(10) UNSIGNED NULL;

내 경험상 메인 테이블에서 MySQL의 SHOW CREATE TABLE을 사용하여 기본 인덱스 열에 대해 설정된 플래그를 정확히 확인한 다음 외래 키 열에 복사하는 것이 좋습니다. 명확하지 않은 "서명되지 않음"과 같은 것이있을 수 있습니다.
Ambulare 2014 년

10

이 스크립트를 실행할 때 데이터베이스의 현재 상태는 어떻습니까? 완전히 비어 있습니까? SQL은 처음부터 데이터베이스를 만들 때 잘 실행되지만 일반적으로 errno 150은 외래 키의 일부인 테이블을 삭제하고 다시 만드는 것과 관련이 있습니다. 100 % 새롭고 새로운 데이터베이스로 작업하지 않는다는 느낌을 받고 있습니다.

SQL 파일을 "소스"-ing 할 때 오류가 발생하면 "source"명령 직후에 MySQL 프롬프트에서 "SHOW ENGINE INNODB STATUS"명령을 실행하여 자세한 오류 정보를 볼 수 있습니다.

수동 입력도 확인할 수 있습니다.

삭제 된 테이블을 다시 생성하는 경우이를 참조하는 외래 키 제약 조건을 준수하는 정의가 있어야합니다. 올바른 열 이름과 유형이 있어야하며 앞에서 설명한 것처럼 참조 된 키에 대한 인덱스가 있어야합니다. 이것이 충족되지 않으면 MySQL은 오류 번호 1005를 반환하고 오류 메시지에서 오류 150을 참조합니다. MySQL이 CREATE TABLE 문에서 오류 번호 1005를보고하고 오류 메시지가 오류 150을 참조하면 외래 키 제약 조건이 올바르게 형성되지 않았기 때문에 테이블 생성에 실패한 것입니다.

MySQL 5.1 참조 설명서 .


5

같은 문제가있는이 스레드를보고있는 사람들의 경우 :

이와 같은 오류가 발생하는 데는 많은 이유가 있습니다. MySQL의 외래 키 오류 (여기에 설명 된 오류 포함)의 원인과 해결 방법에 대한 전체 목록은 다음 링크를 확인하세요.

MySQL 외래 키 오류 및 Errno 150


4

Google을 통해이 SO 항목을 찾는 다른 사용자의 경우 : "NOT NULL"로 정의 된 외래 키 (예정) 열에 대해 SET NULL 작업을 수행하지 않는지 확인하십시오. CHECK ENGINE INNODB STATUS를 기억할 때까지 큰 좌절감을 느꼈습니다.


3

확실히 그렇지는 않지만이 실수는 꽤 흔하고 분명하지 않습니다. 의 대상이 FOREIGN KEY될 수 없습니다 PRIMARY KEY. 나에게 유용한 대답은 다음과 같습니다.

FOREIGN KEY는 항상 다른 테이블의 PRIMARY KEY true 필드를 가리켜 야합니다.

CREATE TABLE users(
   id INT AUTO_INCREMENT PRIMARY KEY,
   username VARCHAR(40));

CREATE TABLE userroles(
   id INT AUTO_INCREMENT PRIMARY KEY,
   user_id INT NOT NULL,
   FOREIGN KEY(user_id) REFERENCES users(id));

3

@andrewdotn이 지적했듯이 가장 좋은 방법은 자세한 오류를 보는 것입니다 (SHOW ENGINE INNODB STATUS; 오류 코드 대신 )를 보는 것입니다.

그 이유 중 하나는 동일한 이름의 인덱스가 이미 존재하거나 다른 테이블에있을 수 있기 때문일 수 있습니다. 실제로 이러한 충돌을 피하기 위해 인덱스 이름 앞에 테이블 이름을 접두사로 붙이는 것이 좋습니다. 예를 들어 대신 idx_userId사용 idx_userActionMapping_userId합니다.


3

먼저 확인하십시오

  1. InnoDB 테이블을 사용하고 있습니다.
  2. FOREIGN KEY의 필드는 소스 필드와 동일한 유형 및 길이 (!)를 갖습니다.

나는 똑같은 문제가 있었고 그것을 고쳤습니다. 한 필드에는 부호없는 INT가 있고 다른 필드에는 정수만 있습니다.


2

유용한 팁, 쿼리를 SHOW WARNINGS;시도한 후 사용 CREATE하면 더 자세한 경고와 함께 오류가 표시됩니다.

    ---------------------------------------------------------------------------------------------------------+
| Level   | Code | Message                                                                                                                                                                                                                                 |
+---------+------+--------------------------------------------------------------------------                          --------------------------------------------------------------------------------------------                          ---------------+
| Warning |  150 | Create table 'fakeDatabase/exampleTable' with foreign key constraint failed. There is no index in the referenced table where the referenced columns appear as the first columns.
|
| Error   | 1005 | Can't create table 'exampleTable' (errno:150)                                                                                                                                                                           |
+---------+------+--------------------------------------------------------------------------                          --------------------------------------------------------------------------------------------                          ---------------+

이 경우에는 내 테이블을 다시 만들 시간입니다!


1

이것은 일반적으로 기존 데이터베이스에 파일을 소스로 넣으려고 할 때 발생합니다. 먼저 모든 테이블 (또는 DB 자체)을 삭제하십시오. 그리고 SET foreign_key_checks = 0;시작과 SET foreign_key_checks = 1;끝에 있는 소스 파일 .


1

이것이 실패하는 또 다른 이유를 찾았습니다 ... 대소 문자를 구분하는 테이블 이름.

이 테이블 정의의 경우

CREATE TABLE user (
  userId int PRIMARY KEY AUTO_INCREMENT,
  username varchar(30) NOT NULL
) ENGINE=InnoDB;

이 테이블 정의는 작동합니다.

CREATE TABLE product (
  id int PRIMARY KEY AUTO_INCREMENT,
  userId int,
  FOREIGN KEY fkProductUser1(userId) REFERENCES **u**ser(userId)
) ENGINE=InnoDB;

이것은 실패하는 반면

CREATE TABLE product (
  id int PRIMARY KEY AUTO_INCREMENT,
  userId int,
  FOREIGN KEY fkProductUser1(userId) REFERENCES User(userId)
) ENGINE=InnoDB;

Windows에서는 작동하고 Unix에서는 실패했다는 사실을 파악하는 데 몇 시간이 걸렸습니다. 다른 사람에게 도움이되기를 바랍니다.


1

Mac OS 용 MySQL Workbench 6.3.

문제점 : DB 다이어그램에서 포워드 엔지니어링을 시도 할 때 테이블 X의 errno 150, 21 개 중 20 개 성공, 1 개 실패. 테이블 X의 FK가 삭제되면 오류가 이전에 실패하지 않았던 다른 테이블로 이동했습니다.

모든 테이블 엔진을 myISAM으로 변경했으며 제대로 작동했습니다.

여기에 이미지 설명 입력


0

또한 실수로 잘못된 데이터베이스에서 작업하고 있지 않은지 확인할 가치가 있습니다. 이 오류는 외부 테이블이없는 경우 발생합니다. MySQL이 왜 그렇게 비밀 스러워야합니까?


0

외래 키가 상위에서 고유 한 것으로 나열되지 않았는지 확인하십시오. 나는 똑같은 문제가 있었고 그것을 독특하지 않은 것으로 구분하여 해결했습니다.


0

제 경우에는 외래 키 필드 인 필드의 이름이 너무 길기 때문입니다. foreign key (some_other_table_with_long_name_id). 더 짧게 시도하십시오. 이 경우 오류 메시지는 약간 오해의 소지가 있습니다.

또한 @Jon이 앞서 언급했듯이 필드 정의는 동일해야합니다 ( unsigned하위 유형에주의).


0

(댓글에 비해 사이드 노트가 너무 큼)

AUTO_INCREMENT매핑 테이블 에는 ID 가 필요하지 않습니다 . 그것을 제거.

변경 PRIMARY KEY(role_id, role_group_id)(중 순서대로). 이렇게하면 액세스가 더 빨라집니다.

양방향 매핑을 원할 수 INDEX있으므로 반대 순서로 두 열에를 추가하십시오 . (할 필요가 없습니다 UNIQUE.)

추가 팁 : http://mysql.rjweb.org/doc.php/index_cookbook_mysql#speeding_up_wp_postmeta



0

테이블을 만들기 전에 아래 줄을 실행하십시오. SET FOREIGN_KEY_CHECKS = 0;

FOREIGN_KEY_CHECKS 옵션은 InnoDB 테이블에 대한 외래 키 제약 조건을 확인할지 여부를 지정합니다.

-외래 키 제약 조건을 확인하도록 지정합니다 (기본값).

SET FOREIGN_KEY_CHECKS = 1;

 

-외래 키 제약 조건을 확인하지 마십시오

SET FOREIGN_KEY_CHECKS = 0;

사용시기 : 테이블을 다시 만들고 부모-자식 순서로 데이터를로드해야 할 때 참조 제약 조건을 일시적으로 비활성화 (FOREIGN_KEY_CHECKS를 0으로 설정)하면 유용합니다.


-1

같은 문제가 발생했지만 부모 테이블이 없었 음을 확인했습니다. 그래서 저는 자식 마이그레이션 앞에서 부모 마이그레이션을 편집합니다. 그냥 해.


1
이 대신 답변의 코멘트 있었어야
hannad 레흐만
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.