26

最近几周我一直在慢慢学习 SQL。我已经学习了所有的关系代数和关系数据库如何工作的基础知识。我现在要做的是了解它是如何实现的。

我遇到的一个绊脚石是 MySQL 中的外键。除了它们存在于 MySQL 的InnoDB存储模式中之外,我似乎找不到太多关于它们的信息。

什么是在 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;
4

5 回答 5

26

假设您的类别和用户表已经存在并且分别包含 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子句中需要列名。

于 2008-10-25T16:57:43.937 回答
10

编辑: Robert 和 Vinko 声明您需要在外键约束中声明引用列的名称。这在 InnoDB 中是必需的,尽管在标准 SQL 中,如果引用的列名与父表中的名称相同,则可以省略它。

我在 MySQL 中遇到的一个特点是外键声明会在以下几种情况下静默失败:

  • 您的 MySQL 安装不包括 innodb 引擎
  • 您的 MySQL 配置文件未启用 innodb 引擎
  • 您不使用 ENGINE=InnoDB 表修饰符声明您的表
  • 外键列与引用表中的主键列的数据类型不完全相同

不幸的是,MySQL 没有给出未能创建外键约束的消息。它只是忽略该请求,并创建没有外键的表(如果您 SHOW CREATE TABLE 帖子,您可能会看到没有外键声明)。我一直认为这是 MySQL 的一个坏特性!

提示:整数数据类型(例如 BIGINT(20))的整数参数不是必需的。它与列的存储大小或范围无关。无论您给出什么参数,BIGINT 的大小始终相同。该数字是指如果您使用 ZEROFILL 列修饰符,MySQL 将填充该列的位数。

于 2008-10-25T17:50:44.797 回答
5

有一些代码显示了如何自己创建外键,以及在 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;
于 2008-10-25T16:50:22.940 回答
4

我同意罗伯特。您在引用子句中缺少列的名称(并且您应该收到错误 150)。我将补充一点,您可以通过以下方式检查表是如何创建的:

SHOW CREATE TABLE posts;
于 2008-10-25T17:01:36.597 回答
2

前面的答案处理外键约束。虽然外键约束对于维护引用完整性绝对有用,但“外键”概念本身是数据关系模型的基础,无论您是否使用约束。

每当您执行equijoin时,您就是在将外键等同于某物,通常是它引用的键。例子:

select *
from 
   Students
inner join
   StudentCourses
on Students.StudentId = StudentCourses.StudentId

StudentCourses.StudentId 是引用Student.StudentId 的外键。

于 2008-10-25T19:48:49.303 回答