再见西城 发表于 2015-1-16 20:08:45

公布玩转MySQL中的外键束缚

到2009年,甲骨文的数据库Oracle已经诞生了30周年,而MySQL却连它的一半时间都没有。微软的SQLServer仅仅比MySQL大两年,但是SQLServer的发布是建立在Sybase的基础上。本文将向读者先容MySQL中的外键束缚。经由过程本文的先容,您会发明当更新父表中的数据行的时分触发对子表数据的级联更新是件十拿九稳的事变。
本文将向读者先容MySQL中的外键束缚。经由过程本文的先容,您会发明当更新父表中的数据行的时分触发对子表数据的级联更新是件十拿九稳的事变。
  1、简介

  利用MySQL开辟过数据库驱动的小型web使用程序的人都晓得,对干系数据库的表举行创立、检索、更新和删除等操纵都是些对照复杂的历程。实际上,只需把握了最多见的SQL语句的用法,并熟习您选择利用的服务器端剧本言语,就足以对付对MySQL表所需的各类操纵了,特别是当您利用了疾速MyISAM数据库引擎的时分。可是,即便在最复杂的情形下,事变也要比我们设想的要庞大很多。上面我们用一个典范的例子举行申明。假定您正在运转一个博客网站,您几近每天更新,而且该站点同意会见者批评您的帖子。

  在这类情形下,我们的数据库形式最少应当包含两个MyISAM表,一个用于寄存您的博客文章,另外一个来处置会见者的批评。很分明,这两个表之间存在一个一对多的干系,以是我们要在第二个表中界说一个外键,以便在更新大概删除数据行时能够坚持数据库的完全性。

  像下面如许的使用程序,不但保护两个表的完全性是一个严格的应战,而最年夜的难点在于我们必需在使用程序级别来保护它们的完全性。这是年夜部分不请求利用事件的web项目在开辟时代所接纳的办法,由于MyISAM表能够供应杰出的功能。

  固然,如许做也是有价值的,正如我后面所说的,使用程序必需保护数据库的完全性和分歧性,这就意味着要完成更庞大的程序计划逻辑来处置各个表之间的干系。固然能够经由过程利用笼统层和ORM模块来简化数据库会见,可是跟着使用程序所需数据表的数目的增添,处置它们所需的逻辑无疑也会随之变得更加庞大。

  那末,关于MySQL来讲,有无数据库级其余外键处置体例来匡助保护数据库完全性的呢?侥幸的是,谜底是一定的!MySQL还能够撑持InnoDB表,使我们能够经由过程一种十分复杂的体例来处置外键束缚。这个特征同意我们能够触发器某些举措,诸如更新和删失落表中的某些数据行以保护预界说的干系。

  凡事有益皆有弊,利用InnoDB表的次要弱点是它们的速率要比MyISAM慢,特别是在必需查询很多表的年夜范围使用程序中,这一点尤其分明。幸亏较新版本MySQL的MyISAM表也已撑持外键束缚。

  本文将先容怎样将外键束缚使用于InnoDB表。别的,我们还将利用一个复杂的基于php的MySQL笼统类来创立有关的示例代码;固然,您也能够利用本人喜好的别的服务器端言语。如今,我们入手下手先容怎样将外键束缚使用于MySQL。

  2、利用外键束缚的机会

  厚道说,在MySQL中利用InnoDB表的时分,纷歧定非用外键束缚不成,但是,为了外键束缚在某些情形下的服从,我们将经由过程后面提到的例子的代码举行详细申明。它包含两个MyISAM表,分离用于寄存博客文章和批评。

  界说数据库形式时,我们要在这两个表之间创建起一对多的干系,办法是在寄存批评的表中创立一个外键,以将个中的数据行(即批评)对应到特定的博客文章。上面是创立示例MyISAM表的基础SQL代码:

DROPTABLEIFEXISTS`test`.`blogs`;

CREATETABLE`test`.`blogs`(

`id`INT(10)UNSIGNEDAUTO_INCREMENT,

`title`TEXT,

`content`TEXT,

`author`VARCHAR(45)DEFAULTNULL,

PRIROSEKEY(`id`)

)ENGINE=MyISAMDEFAULTCHARSET=utf8;


DROPTABLEIFEXISTS`test`.`comments`;

CREATETABLE`test`.`comments`(

`id`INT(10)UNSIGNEDAUTO_INCREMENT,

`blog_id`INT(10)UNSIGNEDDEFAULTNULL,

`comment`TEXT,

`author`VARCHAR(45)DEFAULTNULL,

PRIROSEKEY(`id`)

)ENGINE=MyISAMDEFAULTCHARSET=utf8;
  下面,我们只是界说了两个MyISAM表,它们组成了博客使用程序的数据层。如您所见,第一个表名为blogs,它由一些寄义很分明的字段构成,分离用于寄存每篇博客文章的ID、题目和内容,最初是作者。第二个表名为comments,用于寄存各篇博客文章的有关批评,它将博客文章的ID作为它的外键,从而创建起一对多的干系。

  迄今为止,我们的事情还算轻松,由于我们只是创立了两个复杂的MyISAM表。下一步,我们要做的是利用一些纪录来添补这些表,以便进一步演示在第一个表中删除表项时,应当在另外一个表中实行那些操纵。



  3、更新博客文章并保护数据库的完全性

  后面部分,我们创立了两个MyISAM表,来充任博客使用程序的数据层。固然,下面的先容还很复杂,我们必要做进一步的会商。为此,我们将向这些表中填进一些纪录,办法是利用SQL命令,详细以下所示:

INSERTINTOblogs(id,title,content,author)VALUES(NULL,Titleofthefirstblogentry,Contentofthefirstblogentry,Ian)

INSERTINTOcomments(id,blog_id,comment,author)VALUES(NULL,1,Commentingfirstblogentry,SusanNorton),(NULL,1,Commentingfirstblogentry,RoseWilson)  下面的代码,实践上摹拟了读者Susan和Rose对我们的第一篇博客作出了批评的情形。假定如今我们要用另外一篇文章来更新第一篇博客。固然,这类情形是有大概产生的。

  在这类情形下,为了保护数据库的分歧性,comments表也必需举行响应的更新,要末经由过程手工体例更新,大概经由过程处置数据层的使用程序举行更新。就本例而言,我们将利用SQL命令来完成更新,详细以下所示:

UPDATEblogsSETid=2,title=Titleofthefirstblogentry,content=Contentofthefirstblogentry,author=JohnDoeWHEREid=1

UPDATEcommentsSETblog_id=2WHEREblod_id=1  如前所述,由于第一篇博客的数据项的内容已更新,以是comments表也必需反应出此变更才行。固然,实际中这个更新操纵应当在使用程序层完成,而非手工举行,这就意味着这个逻辑必需利用服务器端言语来完成。

  为了完成这个操纵,关于PHP来讲能够经由过程一个复杂的子历程便可,可是实践上,假如利用了外键束缚的话,对comments表的更新操纵完整能够托付给数据库。

  就像文章后面所说的那样,InnoDBMySQL表对这个功效供应了无缝地撑持。以是,前面部分我们会利用外键束缚从头后面的示例代码。

  4、数据库的级联更新

  上面,我们将使用外键束缚和InnoDB表(而非默许的MyISAM范例)来从头构建后面的示例代码。为此,起首要从头界说这两个示例表,以便它们可使用特定的数据库引擎。为此,可使用以下所示的SQL代码:

DROPTABLEIFEXISTS`test`.`blogs`;

CREATETABLE`test`.`blogs`(

`id`INT(10)UNSIGNEDAUTO_INCREMENT,

`title`TEXT,

`content`TEXT,

`author`VARCHAR(45)DEFAULTNULL,

PRIROSEKEY(`id`)

)ENGINE=InnoDBDEFAULTCHARSET=utf8;


DROPTABLEIFEXISTS`test`.`comments`;

CREATETABLE`test`.`comments`(

`id`INT(10)UNSIGNEDAUTO_INCREMENT,

`blog_id`INT(10)UNSIGNEDDEFAULTNULL,

`comment`TEXT,

`author`VARCHAR(45)DEFAULTNULL,

PRIROSEKEY(`id`),

KEY`blog_ind`(`blog_id`),

CONSTRAINT`comments_ibfk_1`FOREIGNKEY(`blog_id`)REFERENCES`blogs`(`id`)ONUPDATECASCADE

)ENGINE=InnoDBDEFAULTCHARSET=utf8;  这里的代码与之前的代码比拟,一个分明的分歧的地方在于如今的这两个表利用了InnoDB存储引擎,以是可以撑持外键束缚。除此以外,我们还必要注重界说comments表的代码:

CONSTRAINT`comments_ibfk_1`FOREIGNKEY(`blog_id`)REFERENCES`blogs`(`id`)ONUPDATECASCADE  实践上,这个语句是关照MySQLMySQL,当blogs表更新时,也要更新comments表中外键blog_id的值。换句话说,这里所做的就是让MySQL以级联体例保护数据库完全性,这意味着当某个博客更新时,与之相连的正文也要当即反响此变更,主要的是这一功效的完成并不是在使用程序层完成的。

  两个示例MySQL表已界说好了,如今,更新这两个表就像运转一个UPDATE语句一样复杂,以下所示:

"UPDATEblogsSETid=2,title=Titleofthefirstblogentry,content=Contentofthefirstblogentry,author=JohnDoeWHEREid=1"  后面说过,我们无需更新comments表,由于MySQL会主动处置这统统。别的,在试图更新blogs表的数据行的时分,还能够经由过程往除查询的“ONUPDATE”部分大概划定“NOACTION”和“RESTRICT”让MySQL甚么也不做。固然,还可让MySQL做其他事变,这些将在后续的文章平分别加以先容。

  经由过程下面的先容,我想人人已对怎样在MySQL中的InnoDB表分离利用外键束缚有了一个明晰的熟悉,固然,您也能够进一步编写期近的代码,以进一步加深对这一便利的数据库功效的熟悉。

  5、小结

  本文中,我们具体先容了在MySQL中分离利用外键束缚和InnoDB表的基本常识。就像您在本文的示例所看到的那样,当父表的内容产生更新时触发对子表数据项的级联更新是已十拿九稳的事变,同时还申明了处置数据层的使用程序怎样免去对这一特征的完成。固然,我们也能够在父表删除数据行时供应一样的级联效应,这一点我们将在前面的文章中举行论述。


不管怎么样,市场的结果已经证明MySQL具有性价比高、灵活、MySQL学习教程广为使用和具有良好支持的特点。

变相怪杰 发表于 2015-1-18 18:09:46

记得在最开始使用2k的时候就要用到这个功能,可惜2k没有,现在有了作解决方案的朋友会很高兴吧。

山那边是海 发表于 2015-1-24 16:19:32

对递归类的树遍历很有帮助。个人感觉这个真是太棒了!阅读清晰,非常有时代感。

乐观 发表于 2015-2-2 10:53:21

多加的系统视图和实时系统信息这些东西对DBA挑优非常有帮助,但是感觉粒度还是不太细。

若相依 发表于 2015-2-7 18:29:15

作了些试验,发现使用CLR的存储过程或函数在达到一定的阀值的时候,系统性能会呈指数级下滑!这是非常危险的!只使用几个可能没有问题,当一旦大规模使用会造成严重的系统性能问题!

透明 发表于 2015-2-22 23:54:57

不好!如果出了错;不好调试;不好处理!其实web开发将代码分为3层:web层;业务逻辑层和数据访问层;一般对数据库的操作都在数据访问层来做;这样便于调试和维护!而且将来如果是换了数据库的话;你只需要改数据层的代码;其他层的基本可以不变!要是你在jsp中直接调用sql数据库;那么如果换了数据库呢?岂不都要改?如果报了异常呢?怎么做异常处理?

精灵巫婆 发表于 2015-3-7 05:25:27

很多书籍啊,不过个人认为看书太慢,还不如自己学。多做实际的东西,就会遇到很多问题,网上搜下解决问题。不断重复这个过程,在配合sql的F1功能。

莫相离 发表于 2015-3-14 13:46:27

比如日志传送、比如集群。。。

仓酷云 发表于 2015-3-21 09:42:00

如果处理少量数据,比如几百条记录的数据,我不知道这两种情况哪个效率更高,如果处理大量数据呢?比如有表中有20万条记录.
页: [1]
查看完整版本: 公布玩转MySQL中的外键束缚