在更新数据库时使用外键约束 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
咱们看到,如今事情变得简单多了。从这个例子您就能够想象得出,当数据层使用利用外键约束在数据库级别维护各表之间关系的完整性和一致性的数据表的时候,开发与这样的数据层交互的应用程序是多么的简单。