J'essaie donc d'ajouter des contraintes de clé étrangère à ma base de données en tant qu'exigence de projet et cela a fonctionné la première fois ou deux sur des tables différentes, mais j'ai deux tables sur lesquelles une erreur se produit lorsque j'essaie d'ajouter les contraintes de clé étrangère. Le message d'erreur que je reçois est le suivant:
ERREUR 1215 (HY000): impossible d'ajouter une contrainte de clé étrangère
C'est le code SQL que j'utilise pour créer les tables. Les deux tables incriminées sont Patient
et Appointment
.
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;
Pour trouver l'erreur spécifique, exécutez ceci:
SHOW ENGINE INNODB STATUS;
Et regardez dans la section LATEST FOREIGN KEY ERROR
.
Le type de données de la colonne enfant doit correspondre exactement à la colonne parent. Par exemple, puisque medicalhistory.MedicalHistoryID
est une INT
, Patient.MedicalHistory
doit également être une INT
et non une SMALLINT
.
En outre, vous devez exécuter la requête set foreign_key_checks=0
avant d'exécuter la DDL afin de pouvoir créer les tables dans un ordre arbitraire au lieu de devoir créer toutes les tables parent avant les tables enfants correspondantes.
J'avais défini un champ comme "Unsigned" et un autre pas. Une fois que j'ai défini les deux colonnes sur Unsigned, cela a fonctionné.
Essayez d’utiliser le même type de vos clés primaires - int (11) - sur les clés étrangères - smallint (5) - ainsi que.
J'espère que ça aide!
Vérifiez que le codage et le classement des caractères des deux tables sont identiques.
Dans mon cas, l’une des tables utilisait utf8
et l’autre utilisait latin1
.
J'ai eu un autre cas où l'encodage était le même mais le classement différent. Un utf8_general_ci
l'autre utf8_unicode_ci
Vous pouvez exécuter cette commande pour définir le codage et le classement d'une table.
ALTER TABLE tablename CONVERT TO CHARACTER SET utf8 COLLATE utf8_unicode_ci;
J'espère que ça aidera quelqu'un.
Pour définir une clé étrangère dans le tableau B, vous devez définir une clé dans le tableau A.
Dans le tableau A: INDEX id
(id
)
Et puis dans le tableau B,
CONSTRAINT `FK_id` FOREIGN KEY (`id`) REFERENCES `table-A` (`id`)
J'ai eu le même problème et la solution était très simple. Solution: les clés étrangères déclarées dans la table ne doivent pas être définies comme non nulles.
reference: Si vous spécifiez une action SET NULL, assurez-vous de ne pas avoir déclaré les colonnes de la table enfant comme NOT NULL. ( ref )
Assurez-vous que les deux tableaux sont au format InnoDB. Même si on est au format MyISAM, alors, la contrainte de clé étrangère ne fonctionnera pas.
En outre, les deux champs doivent être du même type. Si l’un est INT, l’autre devrait aussi être INT. Si l’un est VARCHAR, l’autre devrait également être VARCHAR, etc.
Vérifiez les règles suivantes:
Vérifie d'abord si les noms sont donnés correctement pour les noms de table
Le second type de données correct donne-t-il à la clé étrangère?
J'ai fait face au problème et j'ai pu le résoudre en m'assurant que les types de données correspondaient exactement.
J'utilisais SequelPro pour ajouter la contrainte et la clé primaire était non signée par défaut.
Vérifiez la signature sur les deux colonnes de votre table. Si la colonne de la table de référence est SIGNED, la colonne de la table référencée devrait également l'être.
Mon problème était que j'essayais de créer la table de relations avant les autres tables!
Une autre cause de cette erreur est lorsque vos tables ou colonnes contiennent des keywords réservés:
Parfois, on les oublie.
Une erreur similaire s'est produite lors de la création de la clé étrangère dans une table Plusieurs-Plusieurs où la clé primaire était composée de 2 clés étrangères et d'une autre colonne normale. J'ai corrigé le problème en corrigeant le nom de la table référencée, à savoir société, comme indiqué dans le code corrigé ci-dessous:
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
);
NOTE: Les tables suivantes ont été extraites de certains sites quand je faisais de la RD sur la base de données. Donc, la convention de nommage n'est pas appropriée.
Pour moi, le problème était, ma table parente avait un jeu de caractères différent de celui de celui que je créais.
Table des parents (PRODUITS)
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
Table d'enfants ayant un problème (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
);
MODIFIÉ POUR
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
J'ai eu une erreur similaire avec deux clés étrangères pour des tables différentes mais avec les mêmes noms de clé! J'ai renommé les clés et l'erreur est partie)
J'ai eu la même erreur. La cause dans mon cas était:
La cause en était: Depuis que j'ai utilisé phpmyadmin pour créer des clés étrangères dans la base de données renommée - les clés étrangères ont été créées avec un préfixe de nom de base de données mais le préfixe de nom de base de données n'a pas été mis à jour. Il y avait donc toujours des références dans la base de données de sauvegarde pointant vers la base de données nouvellement créée.
Avait une erreur similaire, mais dans mon cas, il me manquait de déclarer le pk comme auto_increment.
Juste au cas où cela pourrait être utile à n'importe qui
Ma solution est peut-être un peu embarrassante et explique pourquoi vous devriez parfois regarder ce que vous avez devant vous au lieu de ces messages :)
J'avais déjà fait appel à un ingénieur avant, ce qui signifiait que ma base de données contenait déjà quelques tables, puis je restais assis à essayer de résoudre les problèmes de contraintes de clés étrangères afin de m'assurer que tout était parfait, mais cela se heurtait à la tables précédemment créées, il était donc impossible de l'emporter.
Dans mon cas, une erreur de syntaxe n'a pas été explicitement notifiée par la console MySQL lors de l'exécution de la requête. Cependant, la section SHOW ENGINE INNODB STATUS
de la commande LATEST FOREIGN KEY ERROR
a été signalée,
Syntax error close to:
REFERENCES`role`(`id`) ON DELETE CASCADE) ENGINE = InnoDB DEFAULT CHARSET = utf8
Je devais laisser un espace entre REFERENCES
et role
pour que cela fonctionne.