仓酷云

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 951|回复: 8
打印 上一主题 下一主题

[学习教程] 绝无经由的MySQL数据库中的外键束缚详解

[复制链接]
逍遥一派 该用户已被删除
跳转到指定楼层
楼主
发表于 2015-1-16 20:10:34 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有帐号?立即注册

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

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

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

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

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

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

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

  利用外键束缚的机会

  厚道说,在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表。下一步,我们要做的是利用一些纪录来添补这些表,以便进一步演示在第一个表中删除表项时,应当在另外一个表中实行那些操纵。

  更新并保护数据库的完全性

  后面部分,我们创立了两个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表对这个功效供应了无缝地撑持。以是,前面部分我们会利用外键束缚从头后面的示例代码。

  数据库的级联更新

  上面,我们将使用外键束缚和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表分离利用外键束缚有了一个明晰的熟悉,固然,您也能够进一步编写期近的代码,以进一步加深对这一便利的数据库功效的熟悉。

MySQL已经为支持所有最流行的Web2.0语言做好了准备,诸如Ruby、Ajax等,当然还有PHP。有的业界分析师说过,“每一个Web2.0公司实质上就是一个数据库公司。
再现理想 该用户已被删除
沙发
发表于 2015-1-18 18:19:43 来自手机 | 只看该作者
一直以来个人感觉SQLServer的优化器要比Oracle的聪明。SQL2005的更是比2k聪明了不少。(有次作试验发现有的语句在200万级时还比50万级的相同语句要快show_text的一些提示没有找到解释。一直在奇怪。)
因胸联盟 该用户已被删除
板凳
发表于 2015-1-27 08:10:47 | 只看该作者
我是新手,正在学习数据库和操作系统,深感理论的泛广,唯有一步一步来,但是又感觉时间不够,收集了很多资料却总是没能认真的看完,希望有一个讨论板块,大家共同解决,共同分享,共同努力
透明 该用户已被删除
地板
发表于 2015-2-5 06:59:23 | 只看该作者
语句级快照和事务级快照终于为SQLServer的并发性能带来了突破。个人感觉语句级快照大家应该应用。事务级快照,如果是高并发系统还要慎用。如果一个用户总是被提示修改不成功要求重试时,会杀人的!
莫相离 该用户已被删除
5#
发表于 2015-2-11 08:02:54 | 只看该作者
个人感觉没有case直观。而且默认的第三字段(还可能更多)作为groupby字段很容易造成新手的错误。
蒙在股里 该用户已被删除
6#
发表于 2015-3-2 01:15:18 | 只看该作者
比如,MicrosoftSQLServer2008的某一个版本可以满足现在的这个业务的需要,而且价格还比Oracle11g要便宜,那么这一产品就是适合的。
简单生活 该用户已被删除
7#
发表于 2015-3-11 01:38:01 | 只看该作者
从底层原理到表层引用,书籍多的很。个人认为没有什么那本书好?这样的说法。主要看和个人的学习方法是否适合。
小女巫 该用户已被删除
8#
发表于 2015-3-17 18:51:55 | 只看该作者
groupby子句可以将查询结果分组,并返回行的汇总信息Oracle按照groupby子句中指定的表达式的值分组查询结果。
分手快乐 该用户已被删除
9#
发表于 2015-3-24 21:06:12 | 只看该作者
比如,MicrosoftSQLServer2008的某一个版本可以满足现在的这个业务的需要,而且价格还比Oracle11g要便宜,那么这一产品就是适合的。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|仓酷云 鄂ICP备14007578号-2

GMT+8, 2024-12-29 07:21

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表