2013-01-19 60 views
0

试图用一个MySQL例子来解释参考约束给其他人,而且我不能让这个讨厌的例子工作!它似乎工作,如果我把它定义为一个外键,但我有教科书说,我不必这样做(使其成为一个列级别的参考约束,而不是表级别)。为什么没有引用起作用

问题是,在更新到dept表中的dname之后,为什么emp表中的dname没有更改?

-- SQL CODE BEGINS 
DROP TABLE IF EXISTS dept; 
DROP TABLE IF EXISTS emp; 

CREATE TABLE dept (
    dname CHAR(10), 
    dnum numeric(3,0) 
) ENGINE=InnoDB; 

CREATE TABLE emp (
    dname CHAR(10) REFERENCES dept(dname) ON UPDATE CASCADE, 
    ename CHAR(10) 
) ENGINE=InnoDB; 

INSERT INTO dept VALUES ("AAA", 111); 
INSERT INTO dept VALUES ("BBB", 222); 

INSERT INTO emp VALUES ("CCC", "Carol"); 
INSERT INTO emp VALUES ("AAA", "Alice"); 

SELECT * from dept; 
SELECT * from emp; 
UPDATE dept SET dname="XYZ" WHERE dnum=111; 
SELECT * from dept; 
SELECT * from emp; 

-- SQL CODE ENDS 

ARGH!

回答

1

从MySQL 5.5参考手册中摘录

<剪断>

InnoDB的不能识别或支持“内联参考Specifications”(如在SQL标准中定义的),其中的参考文献中被定义为列说明书的一部分。 InnoDB只有在作为单独的FOREIGN KEY规范的一部分指定时才接受REFERENCES子句。对于其他存储引擎,MySQL服务器解析并忽略外键规范。

< /剪断>

http://dev.mysql.com/doc/refman/5.5/en/create-table.html

我觉得你的两本教科书的作者应该指出的是,他们推荐的做法,增加对列定义“参考”条款,不创建或强制执行外键限制。


为了创建外键约束,您需要目标列上的唯一索引。在你的情况下,你需要一个索引dept(dname)

ALTER TABLE dept ADD CONSTRAINT dept_UX 
    UNIQUE KEY (dname) ; 

有了到位,你可以创建一个外键约束:。

ALTER TABLE emp ADD CONSTRAINT FK_emp_dept 
    FOREIGN KEY (dname) REFERENCES dept(dname) ON UPDATE CASCADE ; 

(通常情况下,一个外键引用表的主键,但唯一的密钥就足够了其实,与InnoDB一样,所需要的只是一个索引,它不一定是唯一的,但我们不想去那里。)

要声明dname是PRIMARY KEY而不是UNIQUE KEY:

ALTER TABLE dept ADD PRIMARY KEY (dname) ; 

REFERENCES子句添加到列定义,我认为,得到由MySQL忽略。(语法被接受,但它不会被记录在数据字典中。如果您使用MyISAM,则无关紧要,因为MyISAM不强制执行外键约束。)

要创建外键约束作为表定义的一部分,我把它放在一个单独的行上:

CREATE TABLE emp (
dname CHAR(10), 
ename CHAR(10), 
CONSTRAINT FK_emp_dept FOREIGN KEY (dname) REFERENCES dept(dname) 
) ENGINE=InnoDB ; 
+0

谢谢!是的,这确实有效。但是,我有两本教科书说我可以只使用“REFERENCES”而不使用FOREIGN KEY,从而使其成为“列级约束”而不是“表级约束”。当然,这些差异也会让我感到不安。 – crawdady

+0

这些教科书似乎在讨论学术理论,而不是实际的实践。 **“理​​论上,理论和实践没有区别,实际上存在。”** – spencer7593

2
  • DECLARE dept.dname AS PRIMARY KEY
  • 创建emp.dname

FULL DDL外键约束:

CREATE TABLE dept 
(
    dname CHAR(10) PRIMARY KEY, 
    dnum numeric(3,0) 
) ENGINE=InnoDB; 

CREATE TABLE emp 
(
    dname CHAR(10) , 
    ename CHAR(10), 
    CONSTRAINT em_FR FOREIGN KEY (dname) 
     REFERENCES dept(dname) ON UPDATE CASCADE 
) ENGINE=InnoDB; 
+0

谢谢!是的,这确实有效。但是,我有两本教科书说我可以只使用“REFERENCES”而不使用FOREIGN KEY,从而使其成为“列级约束”而不是“表级约束”。当然,这些差异也会让我感到不安。 – crawdady

+0

这看起来像是一个奇怪的MySQL'功能',也许是一个可追溯到昔日的遗迹,当你可以声明这样的约束,但他们从来没有执行,使声明毫无意义。如果它不能像你的问题那样执行约束,它应该这样说(给出一个错误)。我主要使用的DBMS会拒绝在您的示例中创建'emp'表,因为目标列上没有唯一约束('无法在被引用表上找到唯一约束或主键')。 –

+0

好的 - 这就是我一直使用MySQL的原因:就像检查一下......它被记录为“..将被解析但不被执行”,这导致我想知道“为什么要解析它? – crawdady

相关问题