MySql如何创建外键

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MySql如何创建外键相关的知识,希望对你有一定的参考价值。

create table volunteer(
志愿者编号 varchar(6) not null,
志愿者姓名 varchar(8),
班级编号 varchar(4),
constraint PK_V primary key (志愿者编号)
);

create table class(
班级编号 varchar(4),
班级名称 varchar(20),
学院 varchar(20),
constraint PK_C primary key(班级编号),
foreign key 班级编号 references volunteer(班级编号)

);

但是老是报错,求解决方法;

mysql添加外键:

为已经添加好的数据表添加外键:
语法:alter table 表名 add constraint FK_ID foreign key(你的外键字段名) REFERENCES 外表表名(对应的表的主键字段名);
例: alter table tb_active add constraint FK_ID foreign key(user_id) REFERENCES tb_user(id)
//FK_ID是外键的名称
/*
CREATE TABLE `tb_active` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`title` varchar(100) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,
`content` text CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,
`user_id` int(11) NOT NULL,
PRIMARY KEY (`id`),
KEY `user_id` (`user_id`),
KEY `user_id_2` (`user_id`),
CONSTRAINT `FK_ID` FOREIGN KEY (`user_id`) REFERENCES `tb_user` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
*/
参考技术A create table volunteer(
志愿者编号 varchar(6) not null,
志愿者姓名 varchar(8),
班级编号 varchar(4),
constraint PK_V primary key (志愿者编号));
create table class(
班级编号 varchar(4),
班级名称 varchar(20),
学院 varchar(20),
constraint PK_C primary key(班级编号),
班级编号 varchar foreign key references volunteer(班级编号));
你这个试下,我试了可以的
希望可以帮到你
SQL 创建外键语句的方法:constraint 外键名字 foreign key references 外键表(外键字段)本回答被提问者采纳
参考技术B 详细说明可以百度搜我的博客: mysql foreign外键详细使用方法和使用事项_2018_lcf

---------下面是使用方法
使用外键的前提:
1. 表储存引擎必须是innodb,否则创建的外键无约束效果。
2. 外键的列类型必须与父表的主键类型完全一致。
3. 外键的名字不能重复(一般使用。
建外键表两种方式(创建表时关联/添加外键)
1) 第一种方式创建表时加外键使用实例:
mysql> create table A( name char(12), id int(8) ,index(id))engine=innodb; //先建立A表,
mysql> create table B( //建立B表,同时做外键
-> id int(9),
-> money int(9),
-> index(id),
-> foreign key(id) references A (id) //这个是必加项,foreign key(B表要关联的字段),references A表名 (对应字段)
-> on delete cascade on update cascade //这里是可选项的,只加一项或都不加都可以的,看需求.
-> )engine=innodb; //这个必须是innodb类型,并且和A表的一致
第二方式在已有的表上做和A表关联的外键(最好是新建好没有记录的,不然会因为记录对不上而创建不成功)
mysql> create table C( //这里先创建一个空表C
-> id int(7),
-> money int(5),
-> index(id)
-> )engine=innodb;
mysql> alter table Cadd constraint abc //在C表上添加和表A关联的外键,constraint 外键名(自己任意取)
-> foreign key(id) references A(id) //和创建时一样的输入
-> on delete cascade on update cascade; //一样是可选项,这行不写也可以通过.
注: @以上的cascade是上面介强的四种模式之一,是可以替换成其它模式的,如写成on update set null
@还可以同时做两个外键,如写成foreign key(id,money) references A(id,money) 即可
@两张表关联字段名可以取不一样名字,但类型必须一致
参考技术C 少一个名键名。给外键起个名

另第二个表有一个逗号不对
参考技术D 最佳答案别加单引号!

如何修复“MySQL 错误:1822。缺少约束索引”关于创建复合外键

【中文标题】如何修复“MySQL 错误:1822。缺少约束索引”关于创建复合外键【英文标题】:How to fix 'MySQL Error: 1822. Missing index for contraint' On creating a composite foreign key 【发布时间】: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';

【问题讨论】:

【参考方案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 说 复合索引 不起作用。

以上是关于MySql如何创建外键的主要内容,如果未能解决你的问题,请参考以下文章

( 10 )MySQL中的外键

MySQL

Mysql主键外键和索引的区别

MySQL 主键外键

Flask-如何理解创建数据模型中外键关联

day2mysql主键外键自增