为什么这个SQL查询有效?

时间:2011-04-14 09:56:58

标签: mysql sql

我正在关注Phil Greenspun's tutorial on SQL.

Phil使用Oracle进行教程,但我使用的是MySQL。以下是我的疑问:

mysql> CREATE TABLE mailing (
    -> email varchar(100) not null primary key,
    -> name varchar(100)
    -> );
Query OK, 0 rows affected (0.01 sec)

mysql> INSERT INTO mailing (email, name) VALUES ('foo@bar.com', 'FooBar');
Query OK, 1 row affected (0.00 sec)

mysql> CREATE TABLE phone (
    -> email varchar(100) not null references mailing,
    -> phone varchar(20)
    -> );
Query OK, 0 rows affected (0.00 sec)

如您所见,我已将email表的phone列设置为参考。

教程说:

  

phone表有一个参考   完整性约束(“引用   mailing“)以确保我们不这样做   记录人们的电子邮件地址   我们不知道他们的名字

那么这个查询怎么起作用?:

mysql> INSERT INTO phone (email, phone) VALUES ('new@new.com', '112223');
Query OK, 1 row affected (0.00 sec)

...请注意,new@new.com表格中没有mailing

我错过了什么?

3 个答案:

答案 0 :(得分:5)

MySQL中的引用仅适用于InnoDB引擎,请按如下方式重写CREATE TABLE:

 CREATE TABLE phone (
    -> email varchar(100) not null references `mailing` (`email`),
    -> phone varchar(20)
    -> ) ENGINE=InnoDB;

默认情况下,MySQL使用忽略“引用”语句的MyISAM引擎。 阅读更多关于在MySQL中创建表的documentation

更新: 外键引用必须放在CREATE TABLE语句之外。谢谢,@ jswolf和@a_horse_with_no_name

CREATE TABLE phone (
-> email varchar(100) not null,
-> phone varchar(20),
-> REFERENCES `mailing` (`email`)
-> ON DELETE NO ACTION
-> ON UPDATE NO ACTION
-> ) ENGINE=InnoDB;

没有测试,但更有可能它会起作用。

答案 1 :(得分:3)

除了Nemoden的回答:

您的下一个问题将是Phil的示例,其中包含MySQL根本不支持的检查约束(并且没有存储引擎执行此操作)。

答案 2 :(得分:1)

作为Nemoden的回答,你应该使用InnoDB,而不是MyISAM。

FOREIGN KEY关系可以(并且应该在MYSQL中)添加如下:

CREATE TABLE phone
( email varchar(100) NOT NULL
, phone varchar(20) DEFAULT NULL

, FOREIGN KEY fk_mailing (email)         --- the "fk_mailing" name is optional
    REFERENCES mailing (email)
) 
  ENGINE=InnoDB 
  DEFAULT CHARSET = utf8 ;               --- or other charset you prefer

从您使用的教程:

  

我正在使用MySQL,我想评论一下我遇到的障碍     我正在按照本页面的教程进行操作。也许其他新手可以从中受益。

     

据我所知:

     

a)MySQL支持表的不同“存储引擎”。这可能是     一件好事。但是,并非所有引擎都支持参考约束。

     

b)对于支持“引用”约束的MySQL表,它必须是InnoDB类型。     在我的安装中(在SuSE Linux上,在标准RPM二进制包之外),这个     是不是的默认值。因此,您必须更改要进行的服务器配置     这是默认值,或者在结束括号后指定“ENGINE = InnoDB”     表定义。

     

c)即使对于InnoDB,上面的Phil描述的语法也不起作用,尽管如此     没有被拒绝,只是被忽略。根据手册,这实际上是只是一个     评论给开发人员这个列应该引用另一列,     即使mysql没有强制执行约束。

     

d)因此,使这种约束工作的唯一方法是:1。制作表格     InnoDB和2.使用“FOREIGN KEY(email)REFERENCES mailing_list(email)”格式     作为表定义中的单独条目。

     

[MySQL甚至不会发出警告!甚至没有提醒这样的参考条款     仅仅是“评论”。它会很高兴地忽略它们并允许任何旧值     那一排。啊。]

  -- Antonio Ramirez, March 19, 2007