MySQL이 외래 키 제약 조건을 추가 할 수 없음


314

그래서 프로젝트 요구 사항으로 데이터베이스에 외래 키 제약 조건을 추가하려고하는데 다른 테이블에서 처음 또는 두 번 작동했지만 외래 키 제약 조건을 추가하려고 할 때 오류가 발생하는 두 개의 테이블이 있습니다. 내가 얻는 오류 메시지는 다음과 같습니다.

오류 1215 (HY000) : 외래 키 제약 조건을 추가 할 수 없습니다

이것은 테이블을 만드는 데 사용하는 SQL이며 두 가지 위반 테이블은 PatientAppointment입니다.

SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0;
SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=1;
SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='TRADITIONAL,ALLOW_INVALID_DATES';

CREATE SCHEMA IF NOT EXISTS `doctorsoffice` DEFAULT CHARACTER SET utf8 ;
USE `doctorsoffice` ;

-- -----------------------------------------------------
-- Table `doctorsoffice`.`doctor`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `doctorsoffice`.`doctor` ;

CREATE  TABLE IF NOT EXISTS `doctorsoffice`.`doctor` (
  `DoctorID` INT(11) NOT NULL AUTO_INCREMENT ,
  `FName` VARCHAR(20) NULL DEFAULT NULL ,
  `LName` VARCHAR(20) NULL DEFAULT NULL ,
  `Gender` VARCHAR(1) NULL DEFAULT NULL ,
  `Specialty` VARCHAR(40) NOT NULL DEFAULT 'General Practitioner' ,
  UNIQUE INDEX `DoctorID` (`DoctorID` ASC) ,
  PRIMARY KEY (`DoctorID`) )
ENGINE = InnoDB
DEFAULT CHARACTER SET = utf8;


-- -----------------------------------------------------
-- Table `doctorsoffice`.`medicalhistory`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `doctorsoffice`.`medicalhistory` ;

CREATE  TABLE IF NOT EXISTS `doctorsoffice`.`medicalhistory` (
  `MedicalHistoryID` INT(11) NOT NULL AUTO_INCREMENT ,
  `Allergies` TEXT NULL DEFAULT NULL ,
  `Medications` TEXT NULL DEFAULT NULL ,
  `ExistingConditions` TEXT NULL DEFAULT NULL ,
  `Misc` TEXT NULL DEFAULT NULL ,
  UNIQUE INDEX `MedicalHistoryID` (`MedicalHistoryID` ASC) ,
  PRIMARY KEY (`MedicalHistoryID`) )
ENGINE = InnoDB
DEFAULT CHARACTER SET = utf8;


-- -----------------------------------------------------
-- Table `doctorsoffice`.`Patient`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `doctorsoffice`.`Patient` ;

CREATE  TABLE IF NOT EXISTS `doctorsoffice`.`Patient` (
  `PatientID` INT unsigned NOT NULL AUTO_INCREMENT ,
  `FName` VARCHAR(30) NULL ,
  `LName` VARCHAR(45) NULL ,
  `Gender` CHAR NULL ,
  `DOB` DATE NULL ,
  `SSN` DOUBLE NULL ,
  `MedicalHistory` smallint(5) unsigned NOT NULL,
  `PrimaryPhysician` smallint(5) unsigned NOT NULL,
  PRIMARY KEY (`PatientID`) ,
  UNIQUE INDEX `PatientID_UNIQUE` (`PatientID` ASC) ,
  CONSTRAINT `FK_MedicalHistory`
    FOREIGN KEY (`MEdicalHistory` )
    REFERENCES `doctorsoffice`.`medicalhistory` (`MedicalHistoryID` )
    ON DELETE CASCADE
    ON UPDATE CASCADE,
  CONSTRAINT `FK_PrimaryPhysician`
    FOREIGN KEY (`PrimaryPhysician` )
    REFERENCES `doctorsoffice`.`doctor` (`DoctorID` )
    ON DELETE CASCADE
    ON UPDATE CASCADE)
ENGINE = InnoDB;


-- -----------------------------------------------------
-- Table `doctorsoffice`.`Appointment`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `doctorsoffice`.`Appointment` ;

CREATE  TABLE IF NOT EXISTS `doctorsoffice`.`Appointment` (
  `AppointmentID` smallint(5) unsigned NOT NULL AUTO_INCREMENT ,
  `Date` DATE NULL ,
  `Time` TIME NULL ,
  `Patient` smallint(5) unsigned NOT NULL,
  `Doctor` smallint(5) unsigned NOT NULL,
  PRIMARY KEY (`AppointmentID`) ,
  UNIQUE INDEX `AppointmentID_UNIQUE` (`AppointmentID` ASC) ,
  CONSTRAINT `FK_Patient`
    FOREIGN KEY (`Patient` )
    REFERENCES `doctorsoffice`.`Patient` (`PatientID` )
    ON DELETE CASCADE
    ON UPDATE CASCADE,
  CONSTRAINT `FK_Doctor`
    FOREIGN KEY (`Doctor` )
    REFERENCES `doctorsoffice`.`doctor` (`DoctorID` )
    ON DELETE CASCADE
    ON UPDATE CASCADE)
ENGINE = InnoDB;


-- -----------------------------------------------------
-- Table `doctorsoffice`.`InsuranceCompany`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `doctorsoffice`.`InsuranceCompany` ;

CREATE  TABLE IF NOT EXISTS `doctorsoffice`.`InsuranceCompany` (
  `InsuranceID` smallint(5) NOT NULL AUTO_INCREMENT ,
  `Name` VARCHAR(50) NULL ,
  `Phone` DOUBLE NULL ,
  PRIMARY KEY (`InsuranceID`) ,
  UNIQUE INDEX `InsuranceID_UNIQUE` (`InsuranceID` ASC) )
ENGINE = InnoDB;


-- -----------------------------------------------------
-- Table `doctorsoffice`.`PatientInsurance`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `doctorsoffice`.`PatientInsurance` ;

CREATE  TABLE IF NOT EXISTS `doctorsoffice`.`PatientInsurance` (
  `PolicyHolder` smallint(5) NOT NULL ,
  `InsuranceCompany` smallint(5) NOT NULL ,
  `CoPay` INT NOT NULL DEFAULT 5 ,
  `PolicyNumber` smallint(5) NOT NULL AUTO_INCREMENT ,
  PRIMARY KEY (`PolicyNumber`) ,
  UNIQUE INDEX `PolicyNumber_UNIQUE` (`PolicyNumber` ASC) ,
  CONSTRAINT `FK_PolicyHolder`
    FOREIGN KEY (`PolicyHolder` )
    REFERENCES `doctorsoffice`.`Patient` (`PatientID` )
    ON DELETE CASCADE
    ON UPDATE CASCADE,
  CONSTRAINT `FK_InsuranceCompany`
    FOREIGN KEY (`InsuranceCompany` )
    REFERENCES `doctorsoffice`.`InsuranceCompany` (`InsuranceID` )
    ON DELETE CASCADE
    ON UPDATE CASCADE)
ENGINE = InnoDB;

USE `doctorsoffice` ;


SET SQL_MODE=@OLD_SQL_MODE;
SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS;
SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS;

답변:


778

특정 오류를 찾으려면 다음을 실행하십시오.

SHOW ENGINE INNODB STATUS;

그리고 LATEST FOREIGN KEY ERROR섹션을보십시오.

자식 열의 데이터 형식은 부모 열과 정확히 일치해야합니다. 때문에 예를 들어, medicalhistory.MedicalHistoryID이다 INT, Patient.MedicalHistory또한 할 필요가 INT아닌 SMALLINT.

또한 set foreign_key_checks=0DDL을 실행하기 전에 조회 를 실행하여 관련 하위 테이블 전에 모든 상위 테이블을 작성하지 않고 임의의 순서로 테이블을 작성할 수 있습니다.


3
데이터 형식 불일치와 foreign_key_checks 모두 문제를 해결했습니다.
joshuaegclark

30
나를 위해 테이블에서 다른 데이터 정렬로 인해 발생했습니다. 하나는 UTF-8이고 다른 하나는 latin1이었습니다.
ug_

6
또한 내 유형과 길이가 일치하더라도 서명되지 않은 INT이므로 "서명되지 않음"을 확인해야했습니다.
timbrown

1
MyISAM 엔진으로 테이블이 자동으로 생성되었습니다! 고마워요
Captain Hypertext

3
감사. set null삭제 하려고 했지만 열이이었습니다 not null.
Matt

142

한 필드를 "서명되지 않음"으로 설정하고 다른 필드는 설정하지 않았습니다. 두 열을 모두 서명되지 않음으로 설정하면 제대로 작동합니다.


ㅋㅋ MySQL은 이런 종류의 것들에 대해 더 정확한 오류 처리를 사용할 수 있습니다.
데이브

82
  • 엔진 은 동일해야합니다. 예 : InnoDB
  • 데이터 유형 은 동일하고 길이가 같아야합니다. 예 : VARCHAR (20)
  • 데이터 정렬 열 문자 집합이 동일해야합니다. 예 : utf8
    감시 : 테이블의 데이터 정렬이 동일하더라도 열의 열이 여전히 다를 수 있습니다.
  • 고유 -외래 키는 참조 테이블에서 고유 한 필드 (일반적으로 기본 키) 를 참조해야합니다.

1
최고의 답변 이제까지 거의 모든 것을 시도한 후에 unique참조 테이블 열에 명시 적으로 추가해야한다는 것이 밝혀졌습니다 Primary Key!!
Yahya

예, 최고의 답변 ... 특히 전나무 첫 포인트! 필자의 경우 마이그레이션 스크립트가 데이터베이스 엔진을 변경하지 않은 마이그레이션 (2.5.14 예약 2.7.2 예약)을 수행 했으므로 새 테이블을 만들 때이 오류가 발생했습니다.
Bernhard

가장 잘 대답 해주세요.
EngineerCoder

확인 / 변경 방법에 대한 팁으로 더 멋질 것입니다. (! 아이디어에 대한 감사) 나에게는 열 수준 데이터 정렬의 차이를했고이 나에게 수정했다 : stackoverflow.com/questions/1294117/...
sjgp

18

동일한 유형의 기본 키 -int (11) -외래 키 -smallint (5) -를 사용하십시오.

그것이 도움이되기를 바랍니다!


mysql> foos (bar_id)에 고유 인덱스 index_bar_id를 만듭니다. ... mysql> alter table foos 제약 조건 추가 index_bar_id 외래 키 (bar_id) 참조 바 (id); sixarm.com/about/…
CookieCoder

11

두 테이블의 문자 인코딩 및 데이터 정렬이 동일한 지 확인하십시오.

내 경우에는 테이블 중 하나가 사용 중이고 utf8다른 하나는을 사용 중이었습니다 latin1.

인코딩이 동일하지만 데이터 정렬이 다른 또 다른 경우가 있습니다. utf8_general_ci다른 하나utf8_unicode_ci

이 명령을 실행하여 테이블의 인코딩 및 데이터 정렬을 설정할 수 있습니다.

ALTER TABLE tablename CONVERT TO CHARACTER SET utf8 COLLATE utf8_unicode_ci;

나는 이것이 누군가를 돕기를 바랍니다.


멋진 @Adegoke, 훌륭한 답변
Edwin Ikechukwu Okonkwo

7

표 B에서 FOREIGN KEY를 설정하려면 표 A에서 KEY를 설정해야합니다.

표 A에서 : INDEX id( id)

그리고 표 B에서

CONSTRAINT `FK_id` FOREIGN KEY (`id`) REFERENCES `table-A` (`id`)

나는 당신이 무슨 말을하는지 잘 모르겠지만 구문이 틀렸다는 것을 알았습니다. 내가하고있는 일 : alter table aircraft add constraint fk_somehting_unique foreign key (operator_id) 참조 조직, 그러나 수행해야합니다 : alter table aircraft add constraint fk_somehting_unique foreign key (operator_id) reference organization (id) ;
Michael Coxon 2016 년

7

나는 같은 문제가 있었고 해결책은 매우 간단했습니다. 솔루션 : 테이블에 선언 된 외래 키가 null이 아니어야합니다.

참조 : SET NULL 조치를 지정하는 경우 하위 테이블의 열을 NOT NULL로 선언하지 않았는지 확인하십시오. ( REF )


4

다음 규칙을 확인하십시오.

  • 먼저 테이블 이름에 대한 이름이 올바른지 확인합니다.

  • 두 번째 올바른 데이터 유형은 외래 키에 제공됩니까?


4

두 테이블이 모두 InnoDB 형식인지 확인하십시오. 하나가 MyISAM 형식 인 경우에도 외래 키 제약 조건이 작동하지 않습니다.

또한 두 가지 필드의 유형이 동일해야합니다. 하나가 INT이면 다른 하나도 INT 여야합니다. 하나가 VARCHAR이면 다른 하나도 VARCHAR이어야합니다.


3

나는 문제에 직면하고 데이터 형식이 정확히 일치하는지 확인하여 문제를 해결할 수있었습니다.

제약 조건을 추가하기 위해 SequelPro를 사용하고 있었고 기본적으로 기본 키를 서명되지 않은 상태로 만들었습니다.


2

두 테이블 열의 서명을 확인하십시오. 참조 테이블 열이 SIGNED이면 참조 테이블 열도 SIGNED 여야합니다.


1

참고 : 다음 표는 데이터베이스에서 일부 R & D를 수행 할 때 일부 사이트에서 가져온 것입니다. 따라서 명명 규칙이 올바르지 않습니다.

나에게 문제는 부모 테이블에 내가 만든 것과 다른 문자 세트가 있다는 것입니다.

부모 테이블 (PRODUCTS)

products | CREATE TABLE `products` (
  `productCode` varchar(15) NOT NULL,
  `productName` varchar(70) NOT NULL,
  `productLine` varchar(50) NOT NULL,
  `productScale` varchar(10) NOT NULL,
  `productVendor` varchar(50) NOT NULL,
  `productDescription` text NOT NULL,
  `quantityInStock` smallint(6) NOT NULL,
  `buyPrice` decimal(10,2) NOT NULL,
  `msrp` decimal(10,2) NOT NULL,
  PRIMARY KEY (`productCode`),
  KEY `productLine` (`productLine`),
  CONSTRAINT `products_ibfk_1` FOREIGN KEY (`productLine`) REFERENCES `productlines` (`productLine`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1

문제가있는 Child Table (PRICE_LOGS)

price_logs | CREATE TABLE `price_logs` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `productCode` varchar(15) DEFAULT NULL,
  `old_price` decimal(20,2) NOT NULL,
  `new_price` decimal(20,2) NOT NULL,
  `added_on` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`),
  KEY `productCode` (`productCode`),
  CONSTRAINT `price_logs_ibfk_1` FOREIGN KEY (`productCode`) REFERENCES `products` (`productCode`) ON DELETE CASCADE ON UPDATE CASCADE
);

수정

price_logs | CREATE TABLE `price_logs` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `productCode` varchar(15) DEFAULT NULL,
  `old_price` decimal(20,2) NOT NULL,
  `new_price` decimal(20,2) NOT NULL,
  `added_on` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`),
  KEY `productCode` (`productCode`),
  CONSTRAINT `price_logs_ibfk_1` FOREIGN KEY (`productCode`) REFERENCES `products` (`productCode`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=latin1 


0

기본 키가 2 개의 외래 키와 다른 일반 열로 구성된 Many to Many 테이블에서 외래 키를 만들 때 비슷한 오류가 발생했습니다. 아래의 수정 된 코드에 표시된 것처럼 참조 된 테이블 이름 즉 회사를 수정하여 문제를 해결했습니다.

create table company_life_cycle__history -- (M-M)
(
company_life_cycle_id tinyint unsigned not null,
Foreign Key (company_life_cycle_id) references company_life_cycle(id) ON DELETE    CASCADE ON UPDATE CASCADE,
company_id MEDIUMINT unsigned not null,
Foreign Key (company_id) references company(id) ON DELETE CASCADE ON UPDATE CASCADE,
activity_on date NOT NULL,
PRIMARY KEY pk_company_life_cycle_history (company_life_cycle_id, company_id,activity_on),
created_on datetime DEFAULT NULL,
updated_on datetime DEFAULT NULL,
created_by varchar(50) DEFAULT NULL,
updated_by varchar(50) DEFAULT NULL
);

0

다른 테이블에 대해 두 개의 외래 키가 있지만 키 이름이 동일한 비슷한 오류가 발생했습니다! 키 이름을 변경했으며 오류가 발생했습니다)


0

비슷한 오류가 있었지만 제 경우에는 pk를 auto_increment로 선언하지 못했습니다.

누군가에게 도움이 될 수 있도록


0

같은 오류가 발생했습니다. 내 경우의 원인은 다음과 같습니다.

  1. 전체 데이터베이스를 복사하여 phpmyadmin을 통해 데이터베이스 백업을 만들었습니다.
  2. 이전 db가 선택하고 동일한 이름으로 새 db를 작성했습니다.
  3. 업데이트 된 테이블과 데이터를 만들기 위해 SQL 스크립트를 시작했습니다.
  4. 오류가 발생했습니다. 또한 foreign_key_checks를 비활성화했을 때. 데이터베이스가 완전히 비었습니다.

그 이유는 다음과 같습니다. phpmyadmin을 사용하여 이름이 바뀐 데이터베이스에 외래 키를 만들었으므로 데이터베이스 이름 접두사로 만들었지 만 데이터베이스 이름 접두사로 작성된 외래 키는 업데이트되지 않았습니다. 따라서 backup-db에 새로 작성된 db를 가리키는 참조가 여전히있었습니다.


0

내 솔루션은 약간 당황스럽고 왜 때때로이 게시물 대신 당신 앞에있는 것을보아야하는지에 대한 이야기를 들려줍니다. :)

나는 이전에 엔지니어를 고용했는데 실패했기 때문에 데이터베이스에 이미 몇 개의 테이블이 있었기 때문에 모든 것이 완벽하다는 것을 확인하려고 외래 키 제약 실패를 해결하려고 노력했지만 이전에 작성된 테이블이므로 우선하지 않았습니다.


0

이 오류의 또 다른 원인은 테이블 또는 열에 예약 키워드가 포함 된 경우입니다 .

때때로 사람들은 이것을 잊어 버립니다.


0

필자의 경우 쿼리를 실행할 때 MySQL 콘솔에서 명시 적으로 알리지 않은 구문 오류가 발생했습니다. 그러나 SHOW ENGINE INNODB STATUS사령부 LATEST FOREIGN KEY ERROR에서는

  Syntax error close to:

  REFERENCES`role`(`id`) ON DELETE CASCADE) ENGINE = InnoDB DEFAULT CHARSET = utf8

나는 사이의 공백을 떠나야했습니다 REFERENCESrole그것이 작동되도록 할 수 있습니다.


0

나를 위해-현재 DB를 참조하는 비 현재 DB에 대한 FK를 만들면 현재 DB 테이블 접두사를 생략 할 수 없습니다.

USE currrent_db;
ALTER TABLE other_db.tasks ADD CONSTRAINT tasks_fk FOREIGN KEY (user_id) REFERENCES currrent_db.users (id);

"currrent_db"를 생략하면 users 테이블의 경우 FK 오류가 발생합니다. INNODB 상태를 보여주는 흥미로운 사실; 이 경우에는 아무 것도 표시하지 않습니다.


-1

나는이 같은 문제가 있었고 부모와 자식 테이블 모두에서 엔진 이름을 Innodb로 수정하고 참조 필드 이름 FOREIGN KEY ( c_id) REFERENCES x9o_parent_table( c_id)를 수정
한 다음 제대로 작동하고 테이블이 올바르게 설치되었습니다. 이것은 누군가를 위해 가득 차게 사용될 것입니다.

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