三、更新博客文章并维护数据库的完整性
前面部分,我们创建了两个MyISAM表,来充当博客应用程序的数据层。当然,上面的介绍还很简单,我们需要做进一步的讨论。为此,我们将向这些表中填入一些记录,方法是使用SQL命令,具体如下所示:
INSERT INTO comments (id, blog_id, comment, author) VALUES (NULL, 1, 'Commenting first blog entry', 'Susan Norton'), (NULL, 1, 'Commenting first blog entry', 'Rose Wilson')
上面的代码,实际上模拟了读者Susan和Rose对我们的第一篇博客作出了评论的情况。假设现在我们要用另一篇文章来更新第一篇博客。当然,这种情况是有可能发生的。
在这种情况下,为了维护数据库的一致性,comments表也必须进行相应的更新,要么通过手工方式更新,或者通过处理数据层的应用程序进行更新。就本例而言,我们将使用SQL命令来完成更新,具体如下所示:
UPDATE comments SET blog_id = 2 WHERE blod_id = 1
如前所述,因为第一篇博客的数据项的内容已经更新,所以comments表也必须反映出此变化才行。当然,现实中这个更新操作应该在应用程序层完成,而非手工进行,这就意味着这个逻辑必须使用服务器端语言来实现。
为了完成这个操作,对于PHP来说可以通过一个简单的子过程即可,但是实际上,如果使用了外键约束的话,对comments表的更新操作完全可以委托给数据库。
就像文章前面所说的那样,InnoDB MySQL表对这个功能提供了无缝地支持。所以,后面部分我们会使用外键约束重新前面的示例代码。
四、数据库的级联更新
下面,我们将利用外键约束和InnoDB表(而非默认的MyISAM类型)来重新构建前面的示例代码。为此,首先要重新定义这两个示例表,以便它们可以使用特定的数据库引擎。为此,可以使用如下所示的SQL代码:
CREATE TABLE `test`.`blogs` (
`id` INT(10) UNSIGNED AUTO_INCREMENT,
`title` TEXT,
`content` TEXT,
`author` VARCHAR(45) DEFAULT NULL,
PRIROSE 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,
PRIROSE 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存储引擎,所以能够支持外键约束。除此之外,我们还需要注意定义comments表的代码:
实际上,这个语句是通知MySQLMySQL,当blogs表更新时,也要更新comments表中外键blog_id的值。换句话说,这里所做的就是让MySQL以级联方式维护数据库完整性,这意味着当某个博客更新时,与之相连的注释也要立即反应此变化,重要的是这一功能的实现并非在应用程序层完成的。
两个示例MySQL表已经定义好了,现在,更新这两个表就像运行一个UPDATE语句一样简单,如下所示:
前面说过,我们无需更新comments表,因为MySQL会自动处理这一切。此外,在试图更新blogs表的数据行的时候,还可以通过去除查询的“ON UPDATE”部分或者规定“NO ACTION”和“RESTRICT”让MySQL什么也不做。当然,还可以让MySQL做其他事情,这些将在后续的文章中分别加以介绍。
通过上面的介绍,我想大家已经对如何在MySQL中的InnoDB表结合使用外键约束有了一个清晰的认识,当然,您也可以进一步编写在即的代码,以进一步加深对这一方便的数据库功能的认识。
五、小结
本文中,我们详细介绍了在MySQL中结合使用外键约束和InnoDB表的基础知识。就像您在本文的示例所看到的那样,当父表的内容发生更新时触发对子表数据项的级联更新是已经轻而易举的事情,同时还说明了处理数据层的应用程序如何免除对这一特性的实现。当然,我们也可以在父表删除数据行时提供同样的级联效应,这一点我们将在后面的文章中进行阐述。