MySQL विदेशी कुंजी बाधा नहीं जोड़ सकता है


314

इसलिए मैं प्रोजेक्ट की आवश्यकता के रूप में अपने डेटाबेस में विदेशी कुंजी बाधाओं को जोड़ने की कोशिश कर रहा हूं और इसने पहली बार या दो अलग-अलग तालिकाओं पर काम किया है, लेकिन मेरे पास दो टेबल हैं, जिन पर विदेशी कुंजी बाधाओं को जोड़ने का प्रयास करते समय मुझे एक त्रुटि मिलती है। मुझे मिलने वाला त्रुटि संदेश है:

ERROR 1215 (HY000): विदेशी कुंजी बाधा नहीं जोड़ सकता

यह वह एसक्यूएल है जिसका उपयोग मैं टेबल बनाने के लिए कर रहा हूं, दो ऑफेंडिंग टेबल हैं Patientऔर 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;

जवाबों:


778

विशिष्ट त्रुटि खोजने के लिए इसे चलाएं:

SHOW ENGINE INNODB STATUS;

और LATEST FOREIGN KEY ERRORअनुभाग में देखें।

चाइल्ड कॉलम के लिए डेटा टाइप पैरेंट कॉलम से बिल्कुल मेल खाना चाहिए। उदाहरण के लिए, चूँकि a medicalhistory.MedicalHistoryIDहै INT, a Patient.MedicalHistoryभी होना चाहिए INT, a नहीं SMALLINT

इसके अलावा, आपको set foreign_key_checks=0DDL को चलाने से पहले क्वेरी को चलाना चाहिए ताकि आप संबंधित चाइल्ड टेबल से पहले सभी पैरेंट टेबल बनाने की आवश्यकता के बजाय एक मनमाने क्रम में टेबल बना सकें।


3
धन्यवाद, डेटा टाइप असंगति और Foreign_key_checks दोनों ने समस्या को ठीक कर दिया!
२०:५३ पर joshuaegclark

30
मेरे लिए तालिकाओं पर एक अलग टकराव के कारण था, एक UTF-8 था और दूसरा लैटिन 1 था।
ug_

6
यह भी सुनिश्चित करना था कि मैंने "अहस्ताक्षरित" चेक किया था क्योंकि यह एक अहस्ताक्षरित INT था, भले ही मेरे प्रकार और लंबाई मेल खाते हों।
टिब्बर

1
मेरी टेबल स्वचालित रूप से MyISAM इंजन के साथ बनाई जा रही थी! धन्यवाद Ike
कप्तान हाइपरटेक्स्ट

3
धन्यवाद। मैं set nullहटाने की कोशिश कर रहा था , लेकिन कॉलम था not null
मैट

142

मैंने एक क्षेत्र को "अनसाइनड" और दूसरे को नहीं के रूप में सेट किया था। एक बार जब मैंने दोनों कॉलम को अनसाइन किया तो यह काम कर गया।


समान। MySQL इस तरह के सामान पर अधिक सटीक त्रुटि हैंडलिंग का उपयोग कर सकता है।
डेव

81
  • इंजन एक ही होना चाहिए जैसे कि InnoDB
  • डेटाटाइप समान होना चाहिए, और समान लंबाई के साथ। उदाहरण के लिए (20)
  • Collation Columns चारसेट समान होना चाहिए। उदाहरण के लिए utf8
    वॉचआउट: भले ही आपकी तालिकाओं में एक ही Collation हो, फिर भी कॉलम अलग-अलग हो सकते हैं।
  • अद्वितीय - विदेशी कुंजी को संदर्भ तालिका में अद्वितीय (आमतौर पर प्राथमिक कुंजी) फ़ील्ड का उल्लेख करना चाहिए ।

1
बेस्ट आवर एवर, लगभग सब कुछ आज़माने के बाद, यह पता चला कि मुझे स्पष्ट रूप uniqueसे संदर्भ तालिका कॉलम में जोड़ना होगा, भले ही यह एक है Primary Key!!
याह्या

हाँ, सबसे अच्छा जवाब कभी ... विशेष रूप से पहले बिंदु में देवदार! मेरे मामले में मैंने एक माइग्रेशन किया (बुक 2.5.24 को 2.7.2 बुक किया), जहां माइग्रेशन स्क्रिप्ट ने डेटाबेस इंजन को नहीं बदला, इसलिए नई टेबल बनाते समय मुझे यह त्रुटि मिली।
बर्नहार्ड

सबसे अच्छा जवाब मुझे भी।
अभियंता

कैसे जांच / परिवर्तन के लिए सुझावों के साथ और भी भयानक होगा। मेरे लिए यह एक कॉलम-स्तरीय कॉलेशन अंतर (विचार के लिए धन्यवाद!) था और इसने मुझे ठीक किया: stackoverflow.com/questions/1294117/…
sjgp

18

अपनी प्राथमिक कुंजी के समान प्रकार का उपयोग करने का प्रयास करें - int (11) - विदेशी कुंजियों पर - smallint (5) - साथ ही।

आशा है ये मदद करेगा!


mysql> foos (bar_id) पर अद्वितीय सूचकांक index_bar_id बनाएं; ... mysql> तालिका परिवर्तन के लिए बाधाएं जोड़ें index_bar_id विदेशी कुंजी (bar_id) संदर्भ बार (आईडी); sixarm.com/about/…
कुकी डिकोडर

11

पुष्टि करें कि वर्ण एन्कोडिंग और दो तालिकाओं के लिए टकराव समान है।

मेरे अपने मामले में, तालिकाओं में से एक का उपयोग किया गया था utf8और दूसरा उपयोग कर रहा था latin1

मेरे पास एक और मामला था जहां एन्कोडिंग समान थी लेकिन कोलाज अलग था। एक utf8_general_ciदूसरे काutf8_unicode_ci

किसी तालिका के लिए एन्कोडिंग और कॉलेशन सेट करने के लिए आप यह कमांड चला सकते हैं।

ALTER TABLE tablename CONVERT TO CHARACTER SET utf8 COLLATE utf8_unicode_ci;

मुझे उम्मीद है इससे किसी को सहायता मिलेगी।


बहुत अच्छा लगा @Adegoke, शानदार जवाब
एडविन

7

तालिका B में एक प्रमुख कुंजी सेट करने के लिए, आपको तालिका A में एक कुंजी सेट करनी होगी।

तालिका A: INDEX id( id) में

और फिर तालिका बी में,

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

मुझे यकीन नहीं है कि आप क्या कह रहे हैं, लेकिन मैंने पाया कि मेरा सिंटैक्स गलत था। मैं कर रहा था: टेबल एयरक्राफ्ट को जोड़ने के लिए constraint fk_somehting_unique विदेशी कुंजी (ऑपरेटर_आईडी) संदर्भ संगठन जोड़ें, लेकिन ऐसा करना चाहिए: टेबल एयरक्राफ्ट constraint fk_somehting_unique विदेशी कुंजी (ऑपरेटर_आईडी) संदर्भ संगठन (आईडी) जोड़ें ;
माइकल कॉक्सन

7

मुझे एक ही समस्या थी और समाधान बहुत सरल था। समाधान: तालिका में घोषित विदेशी कुंजी शून्य नहीं होना चाहिए।

संदर्भ: यदि आप SET NULL क्रिया निर्दिष्ट करते हैं, तो सुनिश्चित करें कि आपने चाइल्ड टेबल में कॉलम को NULL घोषित नहीं किया है। ( संदर्भ )


4

निम्नलिखित नियमों की जाँच करें:

  • पहले जाँच करता है कि क्या नाम तालिका नामों के लिए सही दिए गए हैं

  • दूसरा सही डेटा प्रकार विदेशी कुंजी देता है?


4

कृपया सुनिश्चित करें कि दोनों तालिकाओं InnoDB प्रारूप में हैं। यहां तक ​​कि अगर कोई MyISAM प्रारूप में है, तो, विदेशी कुंजी बाधा अभ्यस्त काम करते हैं।

इसके अलावा, एक और बात यह है कि, दोनों क्षेत्र एक ही प्रकार के होने चाहिए। यदि एक INT है, तो दूसरा भी INT होना चाहिए। यदि एक VARCHAR है, तो दूसरा भी VARCHAR होना चाहिए, आदि।


3

मुझे समस्या का सामना करना पड़ा और यह सुनिश्चित करने में सक्षम था कि डेटा प्रकार बिल्कुल मिलान कर रहे थे।

मैं बाधा डालने के लिए SequelPro का उपयोग कर रहा था और यह प्राथमिक कुंजी को डिफ़ॉल्ट रूप से अहस्ताक्षरित बना रहा था।


2

अपने दोनों टेबल कॉलम पर हस्ताक्षर की जाँच करें। यदि संदर्भित तालिका स्तंभ SIGNED है, तो संदर्भित तालिका स्तंभ भी SIGNED होना चाहिए।


1

नोट: निम्न तालिकाओं को कुछ साइट से लिया गया था जब मैं डेटाबेस पर कुछ आर एंड डी कर रहा था। इसलिए नामकरण सम्मेलन उचित नहीं है।

मेरे लिए, समस्या यह थी, मेरी मूल तालिका में उस चरित्र की तुलना में भिन्न वर्ण सेट था, जिसे मैं बना रहा था।

मूल तालिका (उत्पाद)

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

बाल तालिका जिसमें एक समस्या थी (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 विदेशी कुंजी और एक अन्य सामान्य कॉलम शामिल था। मैंने संदर्भित तालिका नाम अर्थात कंपनी को सुधार कर समस्या को ठीक किया, जैसा कि नीचे दिए गए सही कोड में दिखाया गया है:

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 ने und चुना था।
  3. अपडेटेड टेबल और डेटा बनाने के लिए मैंने एक एसक्यूएल स्क्रिप्ट शुरू की।
  4. मुझे त्रुटि मिली। इसके अलावा, जब मैंने विदेशी_की_चेक अक्षम की। डेटाबेस पूरी तरह से खाली था।

इसका कारण था: चूँकि मैंने नामांकित डेटाबेस में कुछ विदेशी कुंजियाँ बनाने के लिए phpmyadmin का उपयोग किया है - विदेशी कुंजियाँ जहाँ डेटाबेस नाम उपसर्ग के साथ बनाया गया था लेकिन डेटाबेस नाम उपसर्ग अद्यतन नहीं किया गया था। तो अभी भी बैकअप डीबी में नव निर्मित डीबी की ओर इशारा करते हुए संदर्भ थे।


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

मुझे इसके बीच एक व्हाट्सएप छोड़ना पड़ा REFERENCESऔर roleइसे काम करना था।


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);

अगर मैं "करंट_डब" छोड़ देता हूं। उपयोगकर्ताओं की तालिका के लिए, मुझे FK त्रुटि मिलती है। दिलचस्प है कि SHOW इंजन INNODB STATUS; इस मामले में कुछ नहीं दिखा।


-1

मेरे पास यह एक ही मुद्दा था, तब मैंने इनॉब के रूप में इंजन का नाम माता-पिता और बच्चे के दोनों तालिकाओं में सही किया और संदर्भ क्षेत्र का नाम FOREIGN KEY ( c_id) संदर्भों x9o_parent_table( c_id) में सुधार दिया।
ठीक किया, तब यह ठीक काम करता है और तालिकाओं को सही तरीके से स्थापित किया जाता है। यह किसी के लिए पूर्ण उपयोग किया जाएगा।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.