2008-10-25 55 views
19

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

我在这里遇到的一个绊脚石是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; 

回答

19

假设你的类别和用户表已经存在,并且包含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条款中是必需的。

+0

太棒了,谢谢。 – icco 2008-10-25 19:26:03

3

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; 
2

我同意罗伯特。您缺少参考子句中列的名称(并且您应该得到错误150)。我要补充一点,你可以检查表是怎么在现实中创造了:

SHOW CREATE TABLE posts; 
8

编辑:你需要的外键约束声明引用的列名罗伯特和Vinko状态。这在InnoDB中是必需的,但在标准SQL中,如果父表中的名称相同,则允许省略引用的列名称。我在MySQL中遇到

一个特质是,外键宣言将在几种情况下静默失败:

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

不幸的是,MySQL没有提示它没有创建外键约束失败的消息。它只是简单地忽略请求,并创建没有外键的表(如果SHOW CREATE TABLE帖子,则可能看不到外键声明)。我一直认为这是MySQL的一个不好的功能!

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

+0

你能否提供一个关于外键列名声明的参考?根据(http://dev.mysql.com/doc/refman/5.0/en/innodb-foreign-key-constraints.html)中的语法,这不是一个可选参数,它不适用于我,除非我指定它。 – 2008-10-25 18:29:47

+0

是的,你是对的,现在我更仔细地测试它,我确实观察到同样的事情。标准SQL应该允许被引用的列名在主表中是隐含的,但是不幸的是InnoDB不支持这一点。 Mea culpa! – 2008-10-25 18:52:28

1

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

无论何时你做一个equijoin,你都将外键等同于某个东西,通常是它引用的关键字。示例:

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

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