题
过去几周我一直在慢慢学习 SQL。我已经掌握了所有关系代数以及关系数据库如何工作的基础知识。我现在想做的是了解它是如何实现的。
我在这方面遇到的一个绊脚石是 MySQL 中的外键。除了它们存在于 数据库 MySQL 具有的存储架构。
MySQL 中实现外键的简单示例是什么?
这是我编写的模式的一部分,如果您宁愿指出我的缺陷而不是向我展示一个有效的示例,那么它似乎不起作用。
CREATE TABLE `posts` (
`pID` bigint(20) NOT NULL auto_increment,
`content` text NOT NULL,
`time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`uID` bigint(20) NOT NULL,
`wikiptr` bigint(20) default NULL,
`cID` bigint(20) NOT NULL,
PRIMARY KEY (`pID`),
Foreign Key(`cID`) references categories,
Foreign Key(`uID`) references users
) ENGINE=InnoDB;
解决方案
假设您的类别和用户表已经存在并且分别包含cID和uID作为主键,这应该有效:
CREATE TABLE `posts` (
`pID` bigint(20) NOT NULL auto_increment,
`content` text NOT NULL,
`time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`uID` bigint(20) NOT NULL,
`wikiptr` bigint(20) default NULL,
`cID` bigint(20) NOT NULL,
PRIMARY KEY (`pID`),
Foreign Key(`cID`) references categories(`cID`),
Foreign Key(`uID`) references users(`uID`)
) ENGINE=InnoDB;
references
子句中需要列名。
其他提示
编辑: Robert 和 Vinko 指出您需要在外键约束中声明引用列的名称。这在 InnoDB 中是必要的,尽管在标准 SQL 中,如果引用的列名与父表中的名称相同,则允许您省略引用的列名。
我在 MySQL 中遇到的一个特性是外键声明在几种情况下会默默失败:
- 您的 MySQL 安装不包括 innodb 引擎
- 您的 MySQL 配置文件未启用 innodb 引擎
- 您没有使用 ENGINE=InnoDB 表修饰符声明您的表
- 外键列与引用表中的主键列的数据类型不完全相同
不幸的是,MySQL 没有给出任何消息表明它无法创建外键约束。它只是忽略该请求,并创建没有外键的表(如果您显示 CREATE TABLE 帖子,您可能会看到没有外键声明)。我一直认为这是MySQL的一个不好的特性!
提示: 整数数据类型的整数参数(例如BIGINT(20)) 不是必需的。它与列的存储大小或范围无关。无论您给出什么参数,BIGINT 始终具有相同的大小。该数字是指如果使用 ZEROFILL 列修饰符,MySQL 将填充该列的位数。
这个有一些代码显示如何自己创建外键,以及在CREATE TABLE中。
以下是其中一个较简单的例子:
CREATE TABLE parent (
id INT NOT NULL,
PRIMARY KEY (id)
) ENGINE=INNODB;
CREATE TABLE child (
id INT,
parent_id INT,
INDEX par_ind (parent_id),
FOREIGN KEY (parent_id) REFERENCES parent(id)
ON DELETE CASCADE
) ENGINE=INNODB;
我同意罗伯特的观点。您缺少references子句中列的名称(您应该收到错误150)。我将补充一点,您可以通过以下方式检查表格的创建方式:
SHOW CREATE TABLE posts;
以前的答案处理外键约束。虽然外键约束对于保持参照完整性肯定是有用的,但是“外键”的概念仍然是有用的。无论您是否使用约束,本身都是数据关系模型的基础。
每当你进行 equijoin 时,你就等于某事物的外键,通常是它引用的键。例如:
select *
from
Students
inner join
StudentCourses
on Students.StudentId = StudentCourses.StudentId
StudentCourses.StudentId是引用Students.StudentId的外键。