2008-10-25 57 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的外鍵。