2013-01-19 64 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

相關問題