MySQL中的外键?

时间:2008-10-25 16:43:19

标签: sql mysql foreign-keys

过去几周我一直在慢慢学习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;

5 个答案:

答案 0 :(得分:21)

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

答案 1 :(得分:9)

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

我在MySQL遇到的一个特质是外键声明会在几种情况下无声地失败:

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

不幸的是,MySQL没有给出它无法创建外键约束的消息。它只是忽略了请求,并创建了没有外键的表(如果你SHOW CREATE TABLE的帖子,你可能看不到外键声明)。我一直认为这是MySQL的一个不好的功能!

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

答案 2 :(得分:4)

This有一些代码显示如何自己创建外键,以及在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;

答案 3 :(得分:3)

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

SHOW CREATE TABLE posts;

答案 4 :(得分:1)

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

无论何时执行equijoin,您都会将外键等同于某些东西,通常是它引用的密钥。例如:

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

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