在更新數據庫時使用外鍵約束 sql
第一個表存儲一些簡單博客數據,而第二個表則存放這些博客的有關評論。這例子的巧妙之處在於,它給子表定義了一個外鍵約束,從而容許咱們在博客文章被刪除時自動地刪除有關的全部評論。下面給出這兩個表的定義,它們創建了一個一對多的關係: 數據庫
DROP TABLE IF EXISTS `test`.`blogs`; CREATE TABLE `test`.`blogs` ( `id` INT ( 10 ) UNSIGNED AUTO_INCREMENT, `title` TEXT , `content` TEXT , `author` VARCHAR ( 45 ) DEFAULT NULL , PRIMARY KEY (`id`) ) ENGINE = InnoDB DEFAULT CHARSET = utf8; DROP TABLE IF EXISTS `test`.`comments`; CREATE TABLE `test`.`comments` ( `id` INT ( 10 ) UNSIGNED AUTO_INCREMENT, `blog_id` INT ( 10 ) UNSIGNED DEFAULT NULL , `comment` TEXT , `author` VARCHAR ( 45 ) DEFAULT NULL , PRIMARY KEY (`id`), KEY `blog_ind` (`blog_id`), CONSTRAINT `comments_ibfk_1` FOREIGN KEY (`blog_id`) REFERENCES `blogs` (`id`) ON UPDATE CASCADE ) ENGINE = InnoDB DEFAULT CHARSET = utf8;除了給以上兩個InnoDB表定義一些簡單字段外,上述的代碼還使用了一個外鍵約束,使得每當父表的「id」鍵更新時,表comments的相應內容也會級聯更新。給父字段「id」定義約束的代碼以下所示:
CONSTRAINT `comments_ibfk_1` FOREIGN KEY (`blog_id`) REFERENCES `blogs` (`id`) ON UPDATE CASCADE
InnoDB引擎除了能夠規定根據父表完成的操做對子表進行的級聯更新之外,還能夠執行其餘的操做,包括「NO ACTION」和「RESTRICT」,這樣即便父表發生更新或者刪除操做,也不會引發對子表的任何操做。 服務器
如今,根據上面的MySQL表的定義,填充以下所示的數據: spa
INSERT INTO blogs (id, title, content, author) VALUES ( NULL , ' Title of the first blog entry ' , ' Content of the first blog entry ' , ' Tom ' ) INSERT INTO comments (id, blog_id, comment, author) VALUES ( NULL , 1 , ' Commenting first blog entry ' , ' Susan Norton ' ), ( NULL , 1 , ' Commenting first blog entry ' , ' Rose ' )
而後,因爲某種緣由,咱們更新了第一個博客數據,那麼只要運行下列SQL語句,與該博客文章有關的全部評論也會隨之自動更新: code
UPDATE blogs SET id = 2 , title = ' Title of the first blog entry ' , content = ' Content of the first blog entry ' , author = ' John Doe ' WHERE id = 1
這看起來很是不錯,對吧?前面講過,外鍵約束允許您將表之間的關係的維護工做委託給數據庫層,這意味着編寫與數據層交互的應用程序時能夠省去很多的代碼。 blog
此外,咱們也能夠觸發級聯刪除操做,這與前面演示的情形很是相似。所以,下面咱們繼續使用早先定義的兩個示例表來演示當某篇博客文章的數據被刪除時,如何利用外鍵約束刪除相應的評論。 開發
不使用外鍵約束時的數據刪除 博客
爲了說明當父表數據被刪除時,外鍵約束在維護數據庫完整性方面發揮的做用,咱們將重建前面的例子,此次使用MyISAM表。首先,咱們須要定義數據表,具體代碼以下所示: it
DROP TABLE IF EXISTS `test`.`blogs`; CREATE TABLE `test`.`blogs` ( `id` INT ( 10 ) UNSIGNED AUTO_INCREMENT, `title` TEXT , `content` TEXT , `author` VARCHAR ( 45 ) DEFAULT NULL , PRIMARY KEY (`id`) ) ENGINE = MyISAM DEFAULT CHARSET = utf8; DROP TABLE IF EXISTS `test`.`comments`; CREATE TABLE `test`.`comments` ( `id` INT ( 10 ) UNSIGNED AUTO_INCREMENT, `blog_id` INT ( 10 ) UNSIGNED DEFAULT NULL , `comment` TEXT , `author` VARCHAR ( 45 ) DEFAULT NULL , PRIMARY KEY (`id`) ) ENGINE = MyISAM DEFAULT CHARSET = utf8;
好了,咱們已經建好了兩個示例表,須要注意的是,它們使用的是默認的MyISAM數據庫引擎,因此不支持外鍵約束。 class
定義的這兩個表構成了博客應用程序的數據層,接下來咱們在其中填上一些數據,所用的代碼以下所示:
INSERT INTO blogs (id, title, content, author) VALUES ( NULL , ' Title of the first blog entry ' , ' Content of the first blog entry ' , ' Tom ' ) INSERT INTO comments (id, blog_id, comment, author) VALUES ( NULL , 1 , ' Commenting first blog entry ' , ' Susan Norton ' ), ( NULL , 1 , ' Commenting first blog entry ' , ' Rose ' )
實際上,以上代碼片段模擬了博客應用程序運行時,咱們發佈了博客並有人張貼評論時,程序在表blogs中插入一篇博客文章的有關數據,並在子表中插入有關評論的過程。如今,若是咱們刪除了這篇博客,那麼有關的評論也應該隨之刪除。
可是,咱們該如何去作呢?別急,下面咱們以SQL語句爲例說明如何完成此任務:
DELETE FROM blogs WHERE id = 1 DELETE FROM comments WHERE blog_id = 1
固然,在實際狀況下,咱們應該經過服務器端語言來執行這兩個刪除語句,而不是使用原始的SQL命令;可是這裏只是舉例之用,就不用考慮這麼多了。
我想您如今已經弄明白了使用MyISAM表時如何刪除博客數據,以及有關的評論。所以,接下來咱們將從新構建這個例子,不過此次咱們將讓數據表使用InnoDB存儲引擎和一個簡單的外鍵約束。
使用外鍵約束時的數據刪除
恰如您可使用外鍵約束級聯更新數據同樣,InnoDB表還支持級聯刪除,這對於維護那些具備特定關係的數據表的一致性極爲有用。
下面咱們舉例說明,如今從新定義兩個表,以下所示:
DROP TABLE IF EXISTS `test`.`blogs`; CREATE TABLE `test`.`blogs` ( `id` INT ( 10 ) UNSIGNED AUTO_INCREMENT, `title` TEXT, `content` TEXT, `author` VARCHAR( 45 ) DEFAULT NULL , PRIMARY KEY (`id`) ) ENGINE = InnoDB DEFAULT CHARSET = utf8; DROP TABLE IF EXISTS `test`.`comments`; CREATE TABLE `test`.`comments` ( `id` INT ( 10 ) UNSIGNED AUTO_INCREMENT, `blog_id` INT ( 10 ) UNSIGNED DEFAULT NULL , `comment` TEXT, `author` VARCHAR( 45 ) DEFAULT NULL , PRIMARY KEY (`id`), KEY `blog_ind` (`blog_id`), CONSTRAINT `comments_ibfk_1` FOREIGN KEY (`blog_id`) REFERENCES `blogs` (`id`) ON DELETE CASCADE ) ENGINE = InnoDB DEFAULT CHARSET = utf8;
如今,組成咱們虛構的博客應用程序的數據層的兩個表blogs和comments將使用InnoDB存儲引擎。這意味着,它們能利用外鍵約束來刪除與某博客有關的全部評論,當該博客被刪除的時候。
引發級聯刪除的SQL語句以下所示:
CONSTRAINT `comments_ibfk_1` FOREIGN KEY (`blog_id`) REFERENCES `blogs` (`id`) ON DELETE CASCADE
如今,因爲這個約束已經施加於blog表的「id」字段,因此在刪除博客的同時清除有關評論將很是簡單,就像運行一個DELETE命令同樣,具體以下所示:
DELETE FROM blogs WHERE id = 1
咱們看到,如今事情變得簡單多了。從這個例子您就能夠想象得出,當數據層使用利用外鍵約束在數據庫級別維護各表之間關係的完整性和一致性的數據表的時候,開發與這樣的數據層交互的應用程序是多麼的簡單。