外键约束失败


foreign key constraint fails

我有以下表格:

CREATE TABLE IF NOT EXISTS `Person_Categories` (
  `PrsCatID` int(11) NOT NULL auto_increment,
  `PrsCategory` varchar(45) NOT NULL,
  PRIMARY KEY  (`PrsCatID`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 AUTO_INCREMENT=10 ;
CREATE TABLE IF NOT EXISTS `Persons` (
  `PersonID` int(11) NOT NULL auto_increment,
  `FirstName` varchar(45) NOT NULL,
  `LastName` varchar(45) NOT NULL,
  `OrderName` varchar(45) default NULL,
  `Email` varchar(45) NOT NULL,
  `Telephone` varchar(20) default NULL,
  `Mobile` varchar(20) default NULL,
  `StreetAddress` varchar(45) NOT NULL,
  `City` varchar(45) NOT NULL,
  `RegionID` int(2) NOT NULL,
  `PostCode` varchar(10) NOT NULL,
  `CountryID` int(11) NOT NULL,
  `TitleID` int(11) NOT NULL,
  `CIC_MailingList` tinyint(1) NOT NULL,
  `FoundationMember` tinyint(1) NOT NULL,
  `PersonCmts` mediumtext,
  PRIMARY KEY  (`PersonID`),
  KEY `TitleID` (`TitleID`),
  KEY `RegionID` (`RegionID`),
  KEY `CountryID` (`CountryID`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 AUTO_INCREMENT=4 ;

CREATE TABLE IF NOT EXISTS `Persons_PersonCategories` (
  `PersonID` int(11) NOT NULL,
  `PrsCatID` int(11) NOT NULL,
  PRIMARY KEY  (`PersonID`,`PrsCatID`),
  KEY `PrsCatID` (`PrsCatID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
 Constraints for the tables
--
ALTER TABLE `Persons`
  ADD CONSTRAINT `Persons_ibfk_12` FOREIGN KEY (`TitleID`) REFERENCES `Job_Titles` (`TitleID`),
  ADD CONSTRAINT `Persons_ibfk_14` FOREIGN KEY (`CountryID`) REFERENCES `Countries` (`CountryID`),
  ADD CONSTRAINT `Persons_ibfk_15` FOREIGN KEY (`RegionID`) REFERENCES `Regions` (`RegionID`);
ALTER TABLE `Persons_PersonCategories`
  ADD CONSTRAINT `Persons_PersonCategories_ibfk_8` FOREIGN KEY (`PrsCatID`) REFERENCES `Person_Categories` (`PrsCatID`),
  ADD CONSTRAINT `Persons_PersonCategories_ibfk_7` FOREIGN KEY (`PersonID`) REFERENCES `Persons` (`PersonID`);

Persons_PersonCategories是一个n:m关系的链接表。当我试图通过我的php应用程序将PersonID和PrsCatID插入Persons_PersonCategories时,我得到了以下错误:

插入过程中发生错误:

无法添加或更新子行:外键约束失败(ubarry09_andrew/Persons_PersonCategories,约束Persons_PersonCategories_ibfk_7外键(PersonID)引用PersonsPersonID))

以下是插入语句:

INSERT INTO Persons_PersonCategories
VALUES (PersonID, PrsCatID)

Persons和Persons_Categories表由数据填充。

非常感谢,zan

下面的SQL语句是合法的,但它可能不会达到您的目的:

INSERT INTO Persons_PersonCategories
VALUES (PersonID, PrsCatID);

这基本上是尝试插入(NULL, NULL),因为它在创建行之前计算VALUES子句中的表达式。但是表达式在尚未创建的行的上下文中命名列,因此没有可使用的值。因此,它对两者都使用NULL。

PRIMARY KEY列中不允许NULL,当您将NULL值用于主键列时,MySQL会自动提升NULL值。在这种情况下,它将它们提升为整数值0。Persons和PersonCategories表中没有值0,因此会出现FK错误。

试试这个实验:

CREATE TABLE IF NOT EXISTS `Persons_PersonCategories2` (
  `PersonID` int(11) NOT NULL,
  `PrsCatID` int(11) NOT NULL,
  PRIMARY KEY  (`PersonID`,`PrsCatID`),
  KEY `PrsCatID` (`PrsCatID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

也就是说,类似于您创建的表,但没有FK约束。

INSERT INTO Persons_PersonCategories2
VALUES (PersonID, PrsCatID);
SELECT * FROM Persons_PersonCategories2;
+----------+----------+
| PersonID | PrsCatID |
+----------+----------+
|        0 |        0 |
+----------+----------+

当您尝试在父级的引用PK列中不存在的FK列中插入值时,会出现外键约束错误。自动递增主键通常不使用零,因此它注定会失败。

您需要做的是向这个INSERT提供要引用的各个表中的主要值。像这样:

$stmt = $pdo->prepare("INSERT INTO Persons_PersonCategories (PersonID, PrsCatID) 
    VALUES (?, ?)");

使用准备好的语句很容易,而且有助于防止SQL注入错误。然后在执行时提供其他表中的值。这些值会自动绑定到您在准备好的查询中使用的?占位符:

$stmt->execute( array(1234, 5678) );

只要这些值1234和5678对应于您引用的表Persons和PersonCategories中的现有行,外键约束就会得到满足。

看起来您在Persons_PersonCategories表上设置了一个FOREIGN KEY约束,该约束不允许您向Persons_PersonCategories表中添加PersonID,而Persons表中还不存在该约束。您的Persons_PersonCategories表上还有另一个FOREIGN KEY,它只允许您添加Person_Categories表中已经存在的PrsCatID。您似乎正在尝试将PersonID添加到Persons_Categories表中,但Persons表中不存在该PersonID。

在尝试将记录添加到Persons_PersonCategories表之前,请确保要添加到Persons_PersonCategories表格中的PersonID存在于Persons表格中。将PrsCatID添加到此表也是如此;首先确保Person_Category表中存在PrsCatID。如果不希望Persons_PersonCategories表阻止插入Persons和Person_Category表中不存在的值,则必须删除FOREIGN KEYS(或代码示例中显示的CONSTRAINT)。要删除CONSTRAINT,请使用以下行:

ALTER TABLE [TABLE_NAME] DROP FOREIGN KEY [CONSTRAINT_NAME]