【问题标题】:How to fix 'MySQL Error: 1822. Missing index for contraint' On creating a composite foreign key如何修复“MySQL 错误:1822。缺少约束索引”关于创建复合外键
【发布时间】:2019-12-02 03:56:03
【问题描述】:

我正在尝试使用复合外键创建表,但不断遇到错误 Error Code: 1822. Failed to add the foreign key constraint. Missing index for constraint 'fk_contractdateshistoric_contractdates_multiple' in the referenced table 'contractdates'

我正在使用MySQL v8.0.16

我检查了列类型是否不同,但我不确定还有什么问题。

这里是构成问题的表,所有表都制作得很愉快,但最后一个包含复合键的表会导致问题。

CREATE TABLE `contracts` (
  `ID` int(11) NOT NULL AUTO_INCREMENT,
  `Name` varchar(100) DEFAULT NULL,
  `CreationDate` datetime DEFAULT NULL,
  `CreatedBy` varchar(30) DEFAULT NULL,
  `CompletionDate` date DEFAULT NULL,
  `Comments` varchar(100) DEFAULT NULL,
  PRIMARY KEY (`ID`)
);

CREATE TABLE `fieldheading` (
  `ID` int(11) NOT NULL AUTO_INCREMENT,
  `fieldTypeID` int(11) DEFAULT NULL,
  `fieldCode` int(11) DEFAULT NULL,
  `fieldHeading` varchar(100) DEFAULT NULL,
  PRIMARY KEY (`ID`)
);

CREATE TABLE `contractdates` (
 `ID` int(11) NOT NULL AUTO_INCREMENT,
  `DateValue` datetime DEFAULT NULL,
  `ContractID` int(11) NOT NULL,
  `FieldHeadingID` int(11) NOT NULL,
  PRIMARY KEY (`ID`),
  UNIQUE KEY `uq_contractdates_contractID_FieldHeading_ID` (`ContractID`,`FieldHeadingID`),
  KEY `fk_contractdates_contracts_id_idx` (`ContractID`),
  KEY `fk_contractdates_fieldheading_id_idx` (`FieldHeadingID`),
  CONSTRAINT `fk_contractdates_fieldheading_id` FOREIGN KEY (`FieldHeadingID`) REFERENCES `fieldheading` (`id`),
  CONSTRAINT `fk_contractdates_contracts_id` FOREIGN KEY (`ContractID`) REFERENCES `contracts` (`id`)
) COMMENT='Table to hold the dates for a contract, one row is one date for a specific contract';

CREATE TABLE `contractdateshistoric` (
  `ID` int(11) NOT NULL AUTO_INCREMENT,
  `ContractID` int(11) NOT NULL,
  `ContractDateCurrentID` int(11) NOT NULL,
  `FieldHeadingID` int(11) NOT NULL,
  `ChangedByID` int(11) NOT NULL,
  `DateValue` datetime NOT NULL,
  `TimeStampChanged` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`ID`),
  KEY `fk_contractdateshistoric_contractdates_mutiple_idx` (`ContractID`, `FieldHeadingID`, `ContractDateCurrentID`),
  CONSTRAINT `fk_contractdateshistoric_contractdates_multiple` FOREIGN KEY (`ContractID`, `FieldHeadingID`, `ContractDateCurrentID`) REFERENCES `contractdates` (`contractid`, `fieldheadingid`, `id`)
) COMMENT='Audit trail of the dates';

【问题讨论】:

    标签: mysql indexing foreign-keys mysql-workbench


    【解决方案1】:

    由于您在表 contractdates 中使用复合 FK,请尝试添加复合索引

      KEY `fk_contractdates_mutiple_idx` (`ContractID`,`FieldHeadingID`,`ID`)
    

    整个创建语句

    CREATE TABLE `contractdates` (
     `ID` int(11) NOT NULL AUTO_INCREMENT,
      `DateValue` datetime DEFAULT NULL,
      `ContractID` int(11) NOT NULL,
      `FieldHeadingID` int(11) NOT NULL,
      PRIMARY KEY (`ID`),
      KEY `fk_contractdates_contracts_id_idx` (`ContractID`),
      KEY `fk_contractdates_fieldheading_id_idx` (`FieldHeadingID`),
      KEY `fk_contractdates_mutiple_idx` (`ContractID`,`FieldHeadingID`,`ID`),
      CONSTRAINT `fk_contractdates_fieldheading_id` FOREIGN KEY (`FieldHeadingID`) REFERENCES `fieldheading` (`id`),
      CONSTRAINT `fk_contractdates_contracts_id` FOREIGN KEY (`ContractID`) REFERENCES `contracts` (`id`)
    ) COMMENT='Table to hold the dates for a contract, one row is one date for a specific contract';
    

    【讨论】:

      【解决方案2】:

      它试图告诉你“你没有在contractdates上创建一个必要的唯一索引,它涵盖了列(contractid,fieldheadingid,id),所以我不能在contractdatehistoric上创建一个引用这组的外键确定单个父行时的列"

      我不确定你为什么要创建一个引用 3 列的 fk,而contractdates 的 pk 只是 ID 列。

      如果contractdatehistoric 记录引用单个contractdates 记录作为其父项,则历史记录应该有一个contractdateid 列,该列引用contractdates.id - 不需要多个列。复制您用于将合同日期与其父合同相关联的模式,您会没事的

      【讨论】:

      • 我创建了一个引用 3 列的 fk,因为我希望能够加入 contractdateshistoric 而不必加入 contractdatescontractidfieldheadingid 对此至关重要。如果我只有contractdateid 作为外键,这意味着我可以有一个historydate 链接到现有的contractdateid 但包含不存在的contractidfieldheadingid 或@987654329 中不存在的组合@。也许我可以省略contractdatesid,但这仍然会造成多外键问题。如果我错了,请纠正我。
      • 另外,contractdates 中的 fieldheadingid 和 contractid 的组合应该是 UNIQUE 而不是 contractdateshistoric,我会更新问题以反映这一点。
      • Erm.. 当然contractdateshistoric,只是一个自动维护的历史表(由触发器?)不需要这个 FK,因为它只会包含具有有效 contractid 的值/字段标题ID。您不需要对历史表进行 FK,因为它仅从已经 FK 的表中获取其数据。您不能将 ContractDates 表更改为具有不存在的 FieldHeadingId,因此历史表中也不能包含错误数据。如果您想加入与 FK 无关的历史表。即使没有 FK,也可以加入表
      • 但话虽如此,contractdateshistoric 不应该有一个对 contractdates 的 FK,因为它不是 contractdates 的子表,它是一个兄弟表,因此它的条目具有相同的规则,它应该有如果你真的坚持,FKs 合同和现场指挥(但这不是必需的,可能会在某个时候绊倒你
      • 您对触发器部分的看法是正确的,我想我只是想多了,因为这是我最初设计的一部分。
      【解决方案3】:

      我已尝试为列单独创建键,请查找更新后的查询:

      CREATE TABLE `contractdateshistoric` (
          `ID` INT(11) NOT NULL AUTO_INCREMENT,
          `ContractID` INT(11) NOT NULL,
          `ContractDateCurrentID` INT(11) NOT NULL,
          `FieldHeadingID` INT(11) NOT NULL,
          `ChangedByID` INT(11) NOT NULL,
          `DateValue` DATETIME NOT NULL,
          `TimeStampChanged` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
          PRIMARY KEY (`ID`),
          KEY `fk_contractdateshistoric_contractdates_mutiple_idx` (`ContractID`),
          KEY `fk_contractdateshistoric_contractdates_mutiple_idx1` (`FieldHeadingID`),
          KEY `fk_contractdateshistoric_contractdates_mutiple_idx2` (`ContractDateCurrentID`),
          CONSTRAINT `fk_contractdateshistoric_contractdates_multiple` FOREIGN KEY (`ContractID`)
          REFERENCES `contractdates` (`contractid`),
          CONSTRAINT `fk_contractdateshistoric_contractdates_multiple1` FOREIGN KEY (`FieldHeadingID`)
          REFERENCES `contractdates` (`fieldheadingid`),
          CONSTRAINT `fk_contractdateshistoric_contractdates_multiple2` FOREIGN KEY (`ContractDateCurrentID`)
          REFERENCES `contractdates` (`id`)
      );
      

      效果很好。

      【讨论】:

      • OP 说 复合索引 不起作用。
      猜你喜欢
      • 2021-09-19
      • 2017-09-16
      • 2014-12-07
      • 2019-02-27
      • 2016-05-23
      • 1970-01-01
      • 2019-06-06
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多