MySQL数据库技术(04)[MySQL防范]
本文“MySQL数据库技术(04)[MySQL防范]”是由七道奇为您精心收集,来源于网络转载,文章版权归文章作者所有,本站不对其观点以及内容做任何评价,请读者自行判断,以下是其具体内容:
? 目前我们已经具有了所需的全部底子知识;可以将MySQL 投入工作了!本节供应一个教程,帮忙熟习M y S Q L.在完成这个教程时,将成立一个样例数据库和这个数据库中的表,然后增添、检索、删除和改正信息与数据库举行交互.此外,在操作这个样例数据库的历程中,将能学到下列东西:
? ? ■ 若何操纵mysql 客户机程序与MySQL 通信.
? ? ■ SQL 语言的基本语句.(假如您曾经利用过其他R D B M S,从而熟习S Q L,那么浏览一下这个教程,看看SQL 的MySQL 版与您熟习的版本有何差别也是很好的.)正如上一节所述, MySQL 采取客户机/服务器体系构造,此中服务器运行在存放数据库的机械上,而客户机通过网络衔接到服务器.这个教程主要基于mysql 客户机的利用.m y s q l读取您的SQL 查询,将它们发送给服务器,并显示后果.mysql 运行在MySQL 所支持的全部平台上,并供应与服务器交互的最直接的手段,因此,它首先是一个逻辑上的客户机.
? ? 在本书中,我们将用samp_db 作为样例数据库的名称.但是有大概在您完本钱例子的历程中需求利用另一个数据库名.因为大概在您的系统上已经有某个人利用了samp_db 这个名称,大概管理员给您指定了另一个数据库名称.在背面的例子中,无论是哪类情形,都用数
据库的实际名称替换s a m p _ d b.表名可以像例子所显示的那样切确地利用,即便系统中的多个人都具有他们自己的样例数据库也是如此.趁便说一下,在MySQL 中,假若有人利用了相同的表名也没什么关系.一旦各个用户都具有自己的数据库, MySQL 将一向保存这些数据库名,避免各用户彼此干扰.
? ? 1.4.1 基本要求
? ? 为了试验这个教程中的例子,必须安装M y S Q L.分外是必须具有对MySQL 客户机和某个MySQL 服务器的拜候权.呼应的客户机程序必须位于您的机械上.至少需求有m y s q l程序,最好还有m y s q l i m p o r t程序.服务器也可以位于您的机械上,固然这不是必须的.实际上,只要答应衔接到服务器,那么服务器位于何位置都没有关系.若服务器正巧运行在您的机械上,得当的客户机程序又已经安装,那么便可以开始试验了.假如您尚需设法搞到M y S Q L,可参阅附录A"得到和安装软件"的阐明.假如您正自己安装M y S Q L,可参阅这一章,或把它给管理员看.假如网络拜候是通过一个因特网服务商(I S P)举行的,那么可查看该服务商能否拥有M y S Q L.假如该ISP 不供应MySQL 服务,可查看附录J"因特网服务商"以得到某些挑选更合适的服务商的倡议.
? ? 除M y S Q L软件外,还需求得到成立样例数据库及其表的权限.假如您没有这种权限,可以向MySQL 管理员咨询.管理员可通过运行mysql 并公布以下的号令供应这种权限:
? ? MySQL 与mysql 的辨别
? ? 为了避免混合,应当阐明,"M y S Q L"指的是整个MySQL RDBMS,而"m y s q l"代表的是一个特定的客户机程序名.它们的发音都是相同的,但可通过差别的大小写字符和字体来辨别.关于发音,MySQL 的发音为"m y - e s s - q u e u e - e l l".我们知道这是因为MySQL 参考指南中是这样发音的.而SQL 的发音为"s e q u e l"或"e s s - q u e u e - e l l".我不认为哪个发音更好一些.乐意读哪个音都可以,不过在您对别人读的时刻,他大概会用他认为是"精确"的发音对您举行改正.
? ? 前一个号令在paul 从l o c a l h o s t(服务器运行在正运行的同一主机)衔接时,答应它完好拜候samp_db 数据库及它的全部表.它还给出了一个口令s e c r e t.第二个号令与第一个近似,但答应paul 从任何主机上衔接("%"为通配符).也可以用特定的主机名代替"%",使p a u l只能从该主机上举行衔接.(假如您的服务器答应从localhost 匿名拜候,由于服务器搜索受权表查找输入衔接匹配的方法的缘由,这样一个GRANT 语句大概是必须的.)关于G R A N T语句以及设置MySQL 用户账号的更具体信息,可在第11 章"通例的MySQL 管理"找到.
? ? 1.4.2 获得样例数据库的分发包
? ? 这个教程在某些地方要触及来自"样例数据库分发包"中的文件.有的文件含有帮忙来设置样例数据库的查询或数据.为了得到这个分发包,可参阅附录A.在翻开这个分发包时,将成立一个名为samp_db 的目录,此目录中含有所需的文件.无论您在哪个地方试验与样例数据库有关的例子,倡议都移入该目录.
? ? 1.4.3 成立和中止与服务器的衔接
? ? 为了衔接到服务器,从外壳程序(即从Unix 提醒符,或从Windows 下的Dos 掌握台)激活mysql 程序.号令以下:
? ? 此中的"%"在本书中代表外壳程序提醒符.这是UNIX 尺度提醒符之一;另一个为"$".在Windows 下,提醒符近似"c : \ >".
mysql 号令行的options 部份大概是空的,但更大概的是公布一条近似以下的号令:
? ? 在激活mysql 时,有大概没必要供应全部这些选项;切当利用的号令请咨询MySQL 管理员.此外,大概还需求至少指定一个名称和一个口令.
? ? 在刚开始学习MySQL 时,大约会为其安全系统而懊恼,因为它使您难于做自己想做的事.(您必须获得成立和拜候数据库的权限,任什么时刻候衔接到数据库都必须给出自己的名字和口令.)但是,在您通过数据库录入和利用自己的记录后,见解就会即刻改变了.这时您会很赏识MySQL 禁止了其他人窥视(大概更卑劣一些,破坏!)您的资料.
? ? 下面介绍选项的含义:
? ? ■ - h h o s t _ n a m e(可挑选情势:- - h o s t =h o s t _ n a m e)
? ? 但愿衔接的服务器主机.假如此服务器运行在与mysql 相同的机械上,这个选项普通可
省略.
? ? ■ -u u s e r _ n a m e(可挑选的情势:- - u s e r =u s e r _ n a m e)您的MySQL 用户名.假如利用UNIX 且您的MySQL 用户名与注册名相同,则可以省去这个选项;mysql 将利用您的注册名作为您的MySQL 名.在Windows 下,缺省的用户名为O D B C.这大概不一定非常有效.可在号令行上指定一个名字,也可以通过设置USER 变量在环境变量中设置一个缺省名.如用下列set 号令指定paul 的一个用户名:
? ? ■ - p(可挑选的情势:- - p a s s w o r d)
? ? 这个选项奉告mysql 提醒键入您的MySQL 口令.注意:可用-pyour_password 的情势(可挑选的情势: - - p a s s w o r d = y o u r _ p a s s w o r d)在号令行上键入您的口令.但是,出于安全的考虑,最好不要这样做.挑选-p 不跟口令奉告mysql 在启动时提醒您键进口令.比方:
? ? 在看到Enter password: 时,键进口令便可.(口令不会显到屏幕,免得给别人看到.)请注意,MySQL 口令不一定必须与UNIX 或Windows 口令相同.假如完好省略了-p 选项,mysql 就认为您不需求口令,不作提醒.请注意: -h 和-u 选项与跟在它们背面的词有关,无论选项和后跟的词之间能否有空格.而-p 却不是这样,假如在号令行上给出口令, -p 和口令之间一定不加空格.比方,假定我的MySQL 用户名和口令辨别为paul 和s e c r e t,但愿衔接到在我注册的同一机械上运行的服务器上.下面的mysql 号令能完成这项工作:
? ? 在我键入号令后, mysql 显示Enter password: 提醒键进口令.然后我键进口令( * * * * * *表明我键入了s e c r e t).假如一切顺利的话, mysql 显示一串消息和一个" m y s q l >"提醒,表示它正等候我公布查询.完好的启动序列以下所示:
? ? 为了衔接到在其他某个机械上运行的服务器,需求用-h 指定主机名.假如该主机为pit -v i p e r. s n a k e . n e t,则呼应的号令以下所示:
? ? 在背面的阐明mysql 号令行的大都例子中,为简单起见,我们打算省去- h、-u 和-p 选项.并且假定您将会供应任何所需的选项.
有很多设置账号的办法,从而没必要在每次运行mysql 时都在衔接参数中举行键入.这个问题在1 . 5节"与mysql 交互的本领"中介绍.您大概会但愿目前就跳到该节,以便找到一些更易于衔接到服务器的办法.
? ? 在成立了服务器的一个衔接后,可在任什么时刻候键入下列号令来完毕会话:
? ? 还可以键入Control-D 来退出,至少在UNIX 上可以这样.
? ? 1.4.4 公布查询
? ? 在衔接到服务器后,便可以公布查询了.本节介绍有关与mysql 交互应当理解的一些知识.为了在mysql 中输入一个查询,只需键入它便可.在查询的末尾处,键入一个分号(";")并按Enter 键.分号奉告mysql 该查询是完好的.(假如您喜好键入两个字符的话,也可以利用"\ g"终止查询.)在键入一个查询之后, mysql 将其发送到服务器上.该服务器处理此查询并将后果送回m y s q l,mysql 将此后果显示出来.下面是一个简单的查询例子和后果:
? ? 它给出当前的日期和时间.(NOW() 函数本身并没有多大用处,但可将其用于表达式中.如对比当前日期和其另日期的差别.)
mysql 还在后果中显示行数计数.本书在例子中普通不给出这个计数.因为mysql 需求见到分号才发送查询到服务器,所以在单一的行上不需求键入分号.假若有必要,可将一个查询分为几行,以下所示:
? ? 请注意,在键入查询的第一行后,提醒符从‘m y s q l’ 变成了‘- >’;这表示mysql 答应持续键入这个查询.这是一个重要的提醒,因为假如在查询的末尾忘掉了分号,此提醒将有助于提醒您查询尚不完好.不然您会一向等下去,心里烦闷为什么mysql 履行查询为什么这么长的时间还没完;而mysql 也搞不清为什么完毕查询的键入要花您那么多的时间!
? ? 大部份情形下,用大写字符、小写字符或大小写字符混合键入查询没什么关系.下列查询满是等价的:
? ? 本书中的例子用大写字符表示SQL 关键字和函数名,用小写字符表示数据库、表和列名.
? ? 假如在查询中调用一个函数,在函数名和后跟的圆括号中间不答应有空格,例:
? ? 这两个查询看上去差别不大,但第二个失利了,因为圆括号并没有紧跟在函数名的背面.假如已经开始键入一个多行的查询,而又不想当即履行它,可键入‘\ c’ 来跳过(放弃)它,如:
? ? 请注意,提醒符又变回了‘m y s q l >’,这表示mysql 为键入的新查询作好了预备.可将查询存储在一个文件中并奉告mysql 从文件中读取查询而不是等候键盘输入.可操纵外壳程序键入重定向实用程序来完成这项工作.比方,假如在文件my_file.sql 中存放有查
询,可以下履行这些查询:
? ? 可用这种办法调用任何所需的文件.这里用后缀为" . s q l"来表示该文件含有SQL 语句.履行mysql 的这种办法将在输入数据到samp_db 数据库时的"增添新记录"中利用.为了装载一个表,让mysql 从某个文件中读取I N S E RT 语句比每次用手工键入这些语句更为便利.
? ? 本教程的别的部份向您供应了很多可以自己试试的查询.这些查询以‘m y s q l >’ 提醒为前导后跟完毕分号,这些例子普通都给出了查询输出后果.可以按给出的情势键入这些查询,所得到的后果应当与自学质猜中的相同.给出的查询中无提醒符的或无分号语句完毕符的只是用来阐明某个要点,不用履行它们.(假如乐意您可以试一下,但假如试的话,请记着给语句末尾加一个分号.)本书背面的章节中,我们普通不给出‘m y s q l >’ 提醒或SQL 语句的分号.这样做的缘由是为了可以在非mysql 客户机程序的语言环境(如在Perl 脚本中或PHP 脚本中)中公布查询,在这些语言环境中,既无提醒符也不需求分号.在专门针对mysql 输入一个查询的场所会作出呼应的阐明.
? ? 1.4.5 成立数据库
? ? 目前开始成立samp_db 样例数据库及其表,填充这些表并对包含在这些表中的数据举行一些简单的查询.
? ?利用数据库触及几个步骤:
? ?1) 成立(初始化)数据库.
? ?2) 成立数据库中的表.
? ?3) 对表举行数据插入、检索、改正或删除.
? ?检索现有数据是对数据库履行的最简单且常见的操作.别的几个最简单且常见的操作是插入新数据、更新或删除现有数据.较少利用的操作是成立表的操作,而最不常用的操作是成立数据库.
? ?我们将重新开始,先成立数据库,再插入数据,然后对数据举行检索.为了成立一个新的数据库,用mysql 衔接到数据库然后公布C R E ATE DATABASE 语句,此语句指定了数据库名:
? ? 在成立表以及对这些表举行各种操作之前,必须先成立samp_db 数据库.成立数据库后,这个新成立的数据库并非当前数据库.这可从履行下面的查询看出:
? ? 为了使samp_db 成为当前数据库,公布USE 语句便可:
? ? USE 为少数几个不需求终结符的语句之一,当然,加上终结符也不会出错.HELP 是另一个不需求终结符的语句.假如想理解不需求终结符的语句有哪些,可公布HELP 语句.在公布了USE 语句后,samp_db 成为缺省数据库:
? ? 使数据库成为当前数据库的另一个办法是在激活mysql 时在号令行上指定它,以下所示:
? ? 事实上,这是一个命名要利用的数据库的办法.假如需求衔接参数可在数据库名前指定.比方,下列两个号令使我们能衔接到在本地主机和p i t - v i p e r.snake.net 上的samp_db 数据库上:
? ? 除非还有指定,不然背面的例子都假定在激活mysql 时,在号令行上给出samp_db 使其成为当前数据库.假如激活数据库时忘了在号令行上指定数据库,只需公布USE samp_db 语句便可.
? ? 1.4.6 成立表
? ? 本节中,我们将成立样例数据库samp_db 所需的表.我们首先考虑美国历史同盟需求的表.然后再考虑学分保存筹划所需的表.在某些数据库的书籍中,在这里要大讲解析与计划、实体—关系图、尺度程序以及诸如此类的东西.这里确切也可以讲这些东西,但是我宁可只讲点实用的东西,比方说,我们的数据库应当是怎样的:数据库中将包含什么内容,每个表中有哪些数据以及由决意若何表示数据而带来的一些问题.这里所作出的关于数据表示的挑选并非绝对的.在其他场所下,大概会挑选差别的方法来表示近似的数据,这取决于利用的需求以及打算将数据派何用处.
? ? 1. 美国历史同盟所需的表
? ? 美国历史同盟的表计划相当简单:
? ? ■ 总统( p r e s i d e n t )表.此表含有描写每位总统的记录.同盟站点上的联机查验要利用这个表.
? ? ■ 会员( m e m b e r )表.此表用来保护同盟每个会员的当前信息.这些信息将用来成立会员地址名录的书面和联机版本、发送会员资格更新提醒等等.
? ? (1) president表
? ? president 表很简单,因此我们先谈论它.这个表将包含每位美国总统的一些基本信息:
? ? ■ 姓名.姓名在一个表中可用几种方法表示.如,可以用一个单一的列来存放完好的姓名,大概用脱离的列来辨别包容名和姓.当然用单一的列更为简单,但是在利用上会带来一些限制,如:
? ? ■ 假如先输入只闻名的姓名,则不大概对姓举行排序.
? ? ■ 假如先输入只有姓的姓名,就不大概对具闻名的姓名举行显示.
? ? ■ 难以对姓名举行搜索.比方,假如要搜索某个特定的姓,则必须利用一个特定的情势,并且查找与这个情势匹配的姓名.这样较之只查找姓效率更低和更慢.member 表将利用单独的名和姓的列以避免这些限制.名列还存放中名(注:西方国家的姓名普通将名放在前,姓放在后,并且除了闻名和姓外,有时还有中名,这是在位置上介于名和姓之间的中间名字)或首字母.这样应当不会削弱我们大概举行的任何一种排序,因为普通不大概对中名举行排序(大概乃至不会对名举行排序).姓名便可以" Bush, George W. "格局显示,也可以"G e o rge W. B u s h"格局显示.还有一种稍显复杂一点的情形.一个总统( Jimmy Carter)在其姓名的末尾处有一
个" J r. ",这时怎样做?按照名字打印的格局,这个总统的姓名显示为" J a m e s E . C a r t e r, J r."或"C a r t e r, James E., Jr.","J r."与名和姓都没有关系,因此我们将建别的一个字段来存放姓名的后缀.这表明在试图肯定怎样表示数据时,即便一个特别的值也大概会带来问题.它也表明,为什么在将数据放入数据库前,尽大概对数据值的范例举行理解是一个很好的设法.假如对数据理解不够,那么有大概在已经开始利用一个表后,不得不更改该表的构造.这不一定是个灾难,但普通应当避免.
? ? ■ 诞生地(城市和州).就像姓名一样,诞生地也可以用单个列或多个列来表示.利用单列更为简单些,但正如姓名中的情形一样,独立的多个列使我们可以完成用单个列不便利完成的事情.比方,假如城市和州辨别给出,查找各位总统诞生在哪个州的记录就会更简单一些.
? ? ■ 诞生日期和死亡日期.这里,唯一特别的问题是我们不能要求都填上死亡日期,因为有的总统目前还健在.MySQL 供应了一个特别的值N U L L,表示"无值",可将其用在死亡日期列中以表示"仍旧健在".
? ? (2) member 表
? ? 存储历史同盟会员清单的member 表在每个记录都包含单个人员的基本描写信息这一点上,近似于president 表.但是每个member 的记录所含的列更多,member 表的各列以下:
? ? ■ 姓名.利用如president 表一样的三个列来表示:姓、名(假如大概的话还有中名)、后缀.
??■ ID 号.这是开始记录会员时赋给每个会员的唯一值.从前同盟未用ID 号,但目前的记录做得更有系统性,所以最好开始利用ID 号.(我但愿您找到有利于利用M y S Q L并考虑到其他的将它用于历史同盟记录的办法.利用数字,将member 表中的记录与其他与会员有关的表中的记录像关联要更简单一些.)
? ? ■ 终止日期.会员必须按期更新他们的会员资格免得作废.关于某些利用,大概会用到近来更新的日期,但是近更新日期不合适于历史同盟.会员资格可在可变的年纪内(普通为一年、二年、三年或五年)更新,而近来更新的日期将不能表示下一次更新必须在什么时刻举行.此外,历史同盟还答应有毕生会员.我们可以用将来一个很长的日期来表示毕生会员,但是用NULL 仿佛更为符合,因为"无值"在逻辑上对应于"永不终止".
? ? ■ 电子邮件地址.关于有电子邮件地址的会员,这将使他们能很简单地举行彼此之间的通信.作为历史同盟秘书,这使您能电子化地发送更新告诉给会员,而用不着发邮政信函.这比到邮局发送信函更简单,并且也不贵.还可以用电子邮件给会员发送他们的地址名录条目的当前内容,并要求他们在有必要时更新信息.
? ? ■ 邮政地址.这是与没有电子邮件(或没有返复书息)的会员联结所需求的.将辨别利用街道地址、城市、州和Zip 号.街道地址列又可以用于有诸如P.O. Box 123 而不是123 Elm St. 的会员的信箱号.我们假定全部同盟会员全都住在美国.当然,关于具有国际会员的机构,此假定过于简化了.假如但愿处理多个国家的地址,还需求对差别国家的地址格局作一些工作.比方,这里的Zip 号就不是一个国际尺度,有的国家有省而不是州.
? ? ■ 电话号码.与地址字段一样,这个列关于联结会员也是很有效的.
? ? ■ 特别爱好的关键词.假定每个会员普通都对美国历史都有爱好,但大概有的会员对某些范畴有特别的爱好.此列记录了这些特别的爱好.会员可以操纵这个信息来找到其他具有近似爱好的会员.
? ? (3) 成立表
? ? 目前我们已经作好了成立历史同盟表的预备.我们用C R E ATE TABLE 语句来完成这项工作,其普通格局以下:
? ? 此中tbl_name 代表但愿赋予表的名称.column_specs 给出表中列的阐明,以及索引的阐明(假若有的话).索引能使查找更快;我们将在第4 章"查询优化"中对其作进一步的介绍.
president 表的C R E ATE TABLE 语句以下所示:
? ? 假如想自己键入这条语句,则调用m y s q l,使samp_db 为当前数据库:
? ? 然后,键入如上所示的C R E ATE TABLE 语句.(请记着,语句末尾要增添一个分号,不然mysql 将不知道哪儿是语句的末尾.)
为了操纵来自样例数据库分发包的预先写下的描写文件来成立president 表,可从外壳程序运行下列号令:
? ? 不管用哪类办法调用m y s q l,都应当在号令行中数据库名的前面指定衔接参数(主机名、用户名或口令).C R E ATE TABLE 语句中每个列的阐明由列名、范例(该列将存储的值的种类)以及一些大概的列属性构成.president 表中所用的两种列范例为VARCHAR 和D AT E.VA R C H A R(n)代表该列包含可变长度的字符(串)值,其最大长度为n 个字符.可按照盼望字符串能有多长来挑选n 值.
state 定义为VA R C H A R ( 2 );即全部州名都只用其两个字符的缩写来表示.其他的字符串列则需求更长一些,以便存放更长的值.
我们利用过的其他列范例为D AT E.这种列范例表示该列存储的是日期值,这一点也不令人吃惊.而令人吃惊的是,日期的表示以年份开首.其尺度格局为" Y Y Y Y- M M - D D"(比方,"1 9 9 9 - 0 7 - 1 8").这是日期表示的ANSI SQL 尺度.我们用于president 表的唯一列属性为N U L L(值可以贫乏)和NOT NULL(必须填充值).大都列是NOT NULL 的,因为我们总要有一个它们的值.可有NULL 值的两个列是s u ff i x(大都姓名没有后缀)和d e a t h(有的总统仍旧健在,所以没有死亡日期).member 表的C R E ATE TABLE 语句以下所示:
? ? 将此语句键入mysql 或履行下列外壳程序号令:
? ? 从列的范例来看,member 表并不很风趣:全部列中,除了一列之外,其他列都是可变长字符串.这个例外的列就是e x p i r a t i o n,为D ATE 型.终止日期值有一个缺省值为"0 0 0 0 - 0 0 -0 0",这是一个非NULL 的值,它表示未输入合理的日期值.这样做的缘由是expiration 可以是N U L L,它表示一个会员是毕生会员.但是,因为此列可认为N U L L,除非别的指定一个差别的值,不然它将取缺省值" 0 0 0 0 - 0 0 - 0 0".假如成立了一个新会员记录,但忘了指定终止日期,该会员将成为一个毕生会员!通过采取缺省值" 0 0 0 0 - 0 0 - 0 0"的办法,避免了这个问题.它还向我们供应了一种手段,便可以按期地搜索这个值,以找出过去未精确输入终止日期的记录.
? ? 请注意,我们"忘了"放入会员ID 号的列.这是专门为了今后操练利用A LTER TA B L E语句而遗留下的.目前让我们来考证一下MySQL 能否确切如我们所盼望的那样成立了表.在mysql 中,公布下列查询:
? ? 与MySQL 3.23 一样,此输出还包含了显示拜候权限信息的另一个列,这里没有给出,
因为它使每行太长,不易显示.
? ? 这个输出后果看上去和我们所盼望的非常一致,除了state 列的信息显示它的范例为C H A R ( 2 ).这就有点古怪了,我们不是定义它为VARCHAR(2) 了吗?是的,是这样定义的,但是MySQL 已经暗暗地将此范例从VARCHAR 换成了C H A R.缘由是为了使短字符串列的
存储空间操纵更为有效,这里不多谈论.假如但愿具体理解,可参阅第3 章中关于A LT E RTABLE 语句的介绍.但对这里的利用来说,两种范例没有什么差别.
? ? 假如公布一个DESCRIBE member 查询,mysql 也会显示member 表的近似信息.DESCRIBE 在您忘了表中的列名、需求知道列的范例、理解列有多宽等的时刻很有效.它关于理解MySQL 存储表行中列的次序也很有效.列的这个存储次序在利用I N S E RT 或LOAD DATA 语句时非常重要,因为这些语句盼望列值以缺省列的次序列出.DESCRIBE 可以省写为D E S C,大概,假如您喜好键入较多字符,则D E S C R I B Etbl_name 另一个平等的语句为SHOW COLUMNS FROM tbl_name.
? ? 假如忘了表名怎么办?这时可以利用SHOW TA B L E S.关于samp_db 数据库,我们目前
为止成立了两个表,其输出后果以下:
? ? 假如您乃至连数据库名都记不住,可在号令行上调用mysql 而不用给出数据库名,然后公布SHOW DATABASES 查询:
? ? 数据库的列表在差别的服务器上是差别的,但是至少可以看到samp_db 和m y s q l;后一个数据库存放掌握MySQL 拜候权限的受权表.DESCRIBE 与SHOW 查询具有可从外壳程序中利用的号令行平等物,以下:
? % mysqlshow 与SHOW DATABASES 一样列出全部数据库
? % mysqlshow d b _ n a m e 与SHOW TABLES 一样列出给定数据库的表
? % mysqlshow db_name tbl_name 与DESCRIBE tbl_name 一样,列出给定表中的列
? ? 2. 用于学分保存筹划的表
? ? 为了知道学分保存筹划需求什么表,我们来看看在本来学分簿上是怎样记学分的.图1 - 2示出学分簿的一页.该页的主体是一个记录学分矩阵.还有一些对学分有意义的必要信息.学生名和ID 号列在矩阵的一端.(为了简单好看,只列出了四个学生.)在矩阵顶端,记录了举行查验和测试的日期.图中示出9月3号、6号、1 6号和2 3号举行查验, 9月9号和1 0月1号进
行测试.
? ? 为了操纵数据库来记录这些信息,需求一个学分表.这个表中应当包含什么记录呢?很明显,每一行都需求有学生名、查验或测试的日期以及学分.图1-3 示出了用这样的表表示的一些来自学分簿的学分.(日期以MySQL 的表示格局"Y Y Y Y- M M - D D"表示.)
? ? 但是,以这种方法设置表仿佛有点问题.仿佛少了点什么.请看图1 - 3中的记录,我们辨别不出是查验的学分还是测试的学分.假如查验和测试的学分权重差别,在肯定终究的学分等级时知道学分的范例是很重要的.大概可以试着从学分的取值范围来肯定学分的范例(查验的学分普通比测试的学分少),但是这样做很不便利,因为这需求举行判断,并且在数据中也不明显.可以通过记录学分的范例来举行辨别,如对学分表增添一列,此列包含" T"或"Q"以表示是"测试"或是"查验",如图1-4 所示.这具有使学分数据范例清析易辨的长处.不利的地方是这个信息有点冗余.明显对具有同一给定日期的记录,学分的范例列老是取相同的值.9月2 3日的学分老是为" Q"范例,而1 0月1日的学分其范例老是具有" T"范例.这样令人很不称心.假如我们以这种方法记录一组查验或测试的学分,不但要为每个新记录输入相同的日期,并且还要频频反复地输入相同的学分范例.谁会但愿频频输入冗余的信息呢?
? ? 我们可以试试别的一种表示.不在score 表中记录学分范例,而是从日期上辨别它们.我们可以做一个日期列表,用它来记录每个日期发生的"学分事件"(查验或测试).然后可以将学分与这个事件列表中的信息结合,肯定学分是查验学分还是测试学分.这只要将score 表记录中的日期与event 表中的日期相匹配得失事件范例便可.图1 - 5示出这个表的计划并演示了score 表记录与9月2 3日这个日期相关联的工作.通过将score 表中的记录与event 表中记录像对应,我们知道这个学分来自查验.
? ? 这比按照某些猜想来推断学分范例要好得多;我们可以按照明确记录在数据库中的数据来直接得到学分范例.这也比在score 表中记录学分范例更好,因为我们只需对每个范例记录一次.
? ? 但是,在第一次听到这种事情时(即结合利用多个表中的信息),大概会想,"嗯,这是一个好主张,但是不是要做很多工作呢?会不会使工作更复杂了?"在某种程度上,这种设法是对的.处理两个记录表比处理一个要复杂.但是再来观察一下学分簿(见图1 - 2).不是也记录了两套东西吗?考虑下列事实:
? ? ■ 在学分矩阵顶用两个单元记录学分,此中每个单元都是按学生名字和日期(在矩阵的旁边和顶上)举行索引的.这代表了一组记录;与score 表的作用相同.
? ? ■ 怎样知道每个日期代表的事件范例呢?在日期上方写了字符" T"或"Q"!因此,也在矩阵顶上记录了日期和学分范例之间的关系.它代表第二组记录;与event 表的作用相同.
? ? 换句话说,这里倡议在两个表中记录信息与用学分簿记录信息所做的工作没什么差别.唯一差别的是,这两组信息在学分簿中不是那么明显地被脱离.在图1 - 5中所示的event 表的计划中加了一个要求,那就是日期必须是唯一的,因为要用它衔接score 与event 表的记录.换句话说,同一天不能举行两次查验,大概同一天不能举行一次查验和一次测试.不然,将会在score 表中有两个记录并且在event 表中也有两个记录,全都具有相同的日期,这时就不知道应若何将score 的记录与event 的记录举行匹配.假如每天不多于一个学分事件,这就是一个永久不会呈现的问题,但是事实并非如此简单.有时,一天中大概会有不止一个学分事件.我常听有的人说他们的数据,"那种古怪情形从不会呈现."但是,假如这种情形确切呈现时,就必须重新计划表以适应这种情形惹起的问题.最好是预先考虑今后大概呈现的问题,并预先预备好怎样处理他们.因此,我们假定有时大概会需求同一天记录两组学分.我们怎样处理呢?假如呈现这种情形,问题并不难办理.只要对处理数据的方法作一点小的更改,便可以使同一日期上有多个事件而不会惹起问题:
? ? 1) 增添一个列到event 表,并用它来给表中每个记录分配一个唯一的编号.实际上这就给了每个事件一个唯一的ID 号,因此我们称该列为event_id 列.(假如认为这仿佛是做傻事,可看一下图1-2 中的学分簿,此中已经有这个特点了.事件ID 恰好与学分簿分数矩阵中列号类似.这个编号大概没有清楚地写在那儿并标上"事件I D,"但是它确切在那儿.)
? ?2) 当向score 表中输入学分时,输入的是事件ID 而不是日期.这些改变的后果如图1-6 所示.目前衔接score 和event 表时,用的是事件ID 而不是日期,并且不但用event 表来决意每个学分的范例,并且还用它来决意其日期.并且在event 表中不再有日期必须唯一这个限制,而唯一的是事件I D.这表示同一天可以有一打测试和查验,并且可以在记录里边直接保存它们.(毫无疑问,学生们听到这个一定浑身颤抖.)不幸的是,从人的概念来看,图1-6 中的表计划算前一个更不能令人称心.score 表也更为抽象一些,因为它包含的从直观上可以理解的列更少.而图1-4 中此表的计划直观且简单理解,因为那个score 表具有日期和学分范例的列.当前的score 表如图1-6 所示,日期和学分范例的列都没有了.这极大地去除了作为人可以很简单考虑的一切.谁但愿看到此中有"事件I D"的score 表?假若有的话,也不代表我们大大都人.
? ? 此时,可看到可以电子化地完成学分记录,且在赋予学分等级时没必要做各种乏味的手工计算.但是,在考虑了若何实际在一个数据库中表示学分信息后,又会被怎样抽象和拆分构成学分信息的表示难住了.自然会产生一个问题:"根本不利用数据库大概会更好一些?大概MySQL 不合适我?"正如您所猜想的那样,笔者将从否定的方面对这个问题举行答复,不然这本书就没必要再往下写了.不过,在考虑若何做一件工作时,应考虑各种情形并发问能否最好不利用数据库系统(如M y S Q L)而利用一些别的东西(如电子表格等):
? ? ■ 学分簿有行和列,而电子表格也有.这使学分簿和电子表格在概念上和外观上都非常近似.
? ? ■ 电子表格可以完成计算,可以操纵一个计算字段来累计每个学生的学分.但是,要对查验和测试举行加权大概有点麻烦,但这也是可以办得到的.另一方面,假如但愿只查看某部份数据(如只查看学分或测试),举行诸如男孩与女孩的对比,或以一种机动的方法显示合计信息等,情形又大有差别了.电子表格的功效显得要差一些,而关系数据库系统完成这些工作相当简单.别的要考虑的一点是为了在关系数据库中举行表示而对数据举行抽象和分化,这个问题并不真的那么难以对付.只要考虑安置数据库使其不会以一种对您但愿做的事无意义的方法来表示数据便可.但是,在肯定了表示方法之后,就要靠数据库引擎来调和和表示数据了.您必定不会但愿将它视为一堆支离破裂的东西.
? ? 比方,在从score 表中检索学分时,不但愿看到事件I D;但但愿看到日期.这没有什么问题.数据库将会按照事件ID 从event 表中查找出日期.您还大概想要看看是查验的学分或测试的学分.这也不成问题.数据库将用相同的办法查找出学分范例,也是操纵事件I D.请记着,这就是如像MySQL 这样的关系数据库的上风所在,即,使一样东西与另一样东西相关联,以便从多个根源得出信息并以您实际想看到的情势供应出来.在学分保存数据的情形中,MySQL 确切操纵事件ID 将信息组合到了一同,而无需人工来完成这件事.
目前我们先来看看,若何使MySQL 完成这种将一个东西与另一个东西相接洽的工作.
? ? 假定但愿看到1 9 9 9年9月2 3号的学分,针对某个特定日期中给出的事件的学分查询以下所示:
? ? 相当吓人,是吗?这个查询通过将score 表的记录与event 表的记录衔接(关联)来检索学生名、日期、学分和学分的范例.后来果以下所示:
? ? 您必定注意到了,它与图1-4 中给出的表计划相同,并且不需求知道事件ID 便可得出这个后果,只需指出感爱好的日期并让MySQL 查找出哪个学分记录具有该日期便可.假如您一向耽忧抽象和分化会使我们丧失一些东西的话,看到这个世界,就不会有这种耽忧了.
当然,在考虑过查询后,您还大概对其他别的东西产生耽忧.即,这个查询看上去有点长并且也有点复杂;是不是做了很多工作写出这样的东西只是为了查找某个给定日期的学分?是的,确切是这样.但是,在每次想要公布一个查询时,有几种办法可以避免键入多行的S Q L.普通情形下,一旦您决意若何履行这样一个查询并将它保存起来后,便可以按需求多次履行它.我们将在1 . 5节"与mysql 交互的本领"中介绍怎样完成这项工作.
? ? 在上述查询的介绍中,我们有点超前了.不过,这个查询比起我们要实际用来得出学分的查询是有点简单了.缘由是,我们还要对表的计划作更多的改正.我们将采取一个唯一的学生I D,而不在score 表中记录学生名.(即,我们将利用来自学分簿的" I D"列的值而不是来自" N a m e"列的值.)然后,成立另一个称为student 的表来存放name 和student_id 列(见图1 - 7).
? ? 为什么要作出这种改正呢?只有一个缘由,大概有两个学生有相同的名字.采取唯一的学生ID 号可帮忙辨别他们的学分.(这与操纵唯一的事件ID 而不是日期来辨别出相同日期的测试或查验完好近似.)在对表的计划作了这样的改正后,实际用来得到给定日期的学分查询变得更为复杂了一些,这个查询以下:
? ? 假如您不能当即清楚地读懂这个查询的意思的话,也没必要耽忧.在进一步深化这个教程之后,就可以看懂这个查询了.将会从图1 - 7中注意到,在student 表中增添了点学分簿中没有的东西.它包含了一本性别列.这便可以做一些简单的事情,如对班级中男孩和女孩的人数计数;也可以做一些更为复杂的事情,如对比男孩和女孩的学分.我们已经计划完了学分保存的几近全部的表.目前只需求别的
一个表来记录出勤情形便可.这个表的内容相对较为直观,即,一个学生ID 号和一个日期(见图1 - 8).表中的每行表示特定的学生在
给定的日期缺勤.在学分时段末,我们将调用MySQL 的计数功效来汇总此表的内容,以便得出每个学生的缺勤数.
? ? 既然目前已经知道学分保存的各个表的构造,目前可以成立它们了.student 表的C R E ATE TABLE 语句以下:
? ? 将上述语句键入mysql 或履行下列外壳程序号令:
? ?C R E ATE TABLE 语句成立了一个名为student 的表,它含有三列,辨别为: n a m e、s e x和s t u d e n t _ i d.name 是一个可变长的字符串列,最多可存放20 个字符.这个名字的表示比历史同盟表中所用的表示要简单,它只用了单一的列而不是分别的名和姓列.这是因为我们已经预先知道,不存在无需做别的的工作就使得在多个列上工作得更好的查询样例.sex 表示学生是男孩还是女孩.这是一个E N U M(列举)列,表示只能取明确地列在阐明中的值之一,这里列出的值为:"F"和"M",辨别表示女和男.在某列只具有一组有限值时,ENUM 范例非常有效.我们可以用CHAR(1) 来替换它,但是ENUM 更明确规定了列可以取什么值.假如对包含一个ENUM 列的表公布一条DESCRIBE tbl_name 语句,MySQL 将切当地显示可取的值有哪些.趁便说一下, ENUM 列中的值不一定只是单个字符.此列还可以定义为E N U M(‘f e m a l e’,‘m a l e’).
? ? student_id 为一个整数型列,它将包含唯一的ID 号.普通,大约会从一此中央资料根源处(如学校办公室)获得学生的ID 号,但在这里是我们自己定的.固然student_id 列只包含一个数,但其定义包含几个部份:
? ? ■ INT 阐明此列的值必须取整数(即无小数部份).
? ? ■ UNSIGNED 不答应负数.
? ? ■ NOT NULL 表示此列的值必须填入.(任何学生都必须有一个ID 号.)
? ? ■ A U TO_INCREMENT 是MySQL 中的一个特别的属性.其作用为:假如在成立一个新的student 表记录时遗漏了student_id 的值(或为N U L L),MySQL 自动地生成一个大于当前此列中最大值的唯一ID 号.在录入学生表时将用到这个这特点,录入学生表时可以只给出name 和sex 的值,让MySQL 自动生成student_id 列值.
? ? ■ P R I M A RY KEY 表示呼应列的值为快速查找举行索引,并且列中的每个值都必须是惟一的.这样可避免同一名字的I D呈现两次,这关于学生ID 号来说是一个必须的特点.(不但如此,并且MySQL 还要求每个A U TO_INCREMENT 列都具有一个惟一索引.)假如您不睬解A U TO_INCREMENT 和P R I M A RY KEY 的含义,只要将其想像为一种为每个学生产生ID 号的魔术办法便可.除了要求值唯一外,没有什么别的东西.请注意:假如确切打算从学校办公室获得学生ID 号而不是自动生成它们,则可以按相同的办法定义student_id 列,只不过不定义A U TO_INCREMENT 属性便可.event 表以下定义:
? 将此语句键入mysql 或履行下列外壳程序的号令:
? ? 全部列都定义为NOT NULL,因为它们中任何一个值都不能省略.date 列存储尺度的MySQL DATE 日期值,格局为"Y Y Y Y- M M - D D"(首先是年).type 代表学分范例.像student 表中的sex 一样,type 也是一个列举列.所答应的值为"T"和"Q",辨别表示"测试"和"查验".event_id 是一个AUTO_INCREMENT 列,近似于student 表中的student_id 列.采取AUTO_INCREMENT 答应生成唯一的事件ID 值.正如student 表中的student_id 列一样,与值的惟一性相比,某个特定的值并不重要.score 表以下定义:
? ? 将此语句键入mysql 或履行下列外壳程序的号令:
? ? score 为一个INT (整型)列.即,假定学分值老是为一个整数.假如但愿使学分值具有小数部份,如5 8 . 5,应当采取浮点列范例,如F L O AT 或D E C I M A L.student_id 列和event_id 列都是整型,辨别表示每个学分所对应的学生和事件.通过操纵它们来衔接到student 和event 表,我们可以知道学生名和事件的日期.我们将两个列构成了P R I M A RY KEY.这保证我们不会对同一查验或测试反复一个学生的学分.并且,这样还很简单在今后更改某个学分.比方,在发现学分录入错时,可以在操纵MySQL 的R E P L A C E语句放入一个新记录,替换掉旧的记录.不需求履行DELETE 语句与I N S E RT 语句;M y S Q L自动替我们做了.请注意,它是惟一的event_id 和student_id 的组合.在score 表中,二者自身都大概不惟一.一个event_id 值可有多个学分记录(每个学生对应一个记录),而每个student_id 值都对应多个记录(每个查验和测试有一个记录).用于出勤情形的absence 表以下定义:
? ? 将此语句键入mysql 或履行下列外壳程序的号令:
? ? student_id 和date 列二者都定义为NOT NULL,不答应省略值.应定义这两列的组合为主键,免得不当心成立了反复的记录.重要的是不要对同一天某个学生的缺旷举行反复计数.
? ? 1.4.7 增添新记录
? ? 至此,我们的数据库及其表都已经成立了,在下一节"检索信息"中,我们将看到怎样从数据库中取出数据.目前我们先将一些数据放入表中.在数据库中加入数占据几种办法.可通过公布I N S E RT 语句手工将记录插入某个表中.还可以通过从某个文件读取它们来增添记录,在这个文件中,记录既可以是操纵L O A DD ATA 语句或mysqlimport 实用程序装入的原始数据值,也可以是预先写成可馈入mysql 的I N S E RT 语句的情势.本节介绍将记录插入表的每种办法.您所应做的是练习各种办法以明了它们是若何起作用的.然后到本节完毕处运行那儿给出的号令来排除表并重装它们.这样做,可以保证表中含有作者撰写下一节时所处理的相同记录,您也能得到相同的后果.让我们开始操纵I N S E RT 语句来增添记录,这是一个SQL 语句,需求为它指定但愿插入数据行的表或将值按行放入的表.I N S E RT 语句具有几种情势:
? ? ■ 可指定全部列的值
? ? 比方:
? ? "I N TO"一词自MySQL 3.22.5 以来是可选的.(这一点对其他情势的I N S E RT 语句也成立.)VALUES 表必须包含表中每列的值,并且按表中列的存放次序给出.(普通,这就是成立表时列的定义次序.假如不能必定的话,可以利用DESCRIBE tbl_name 来查看这个次序.)在MySQL 中,可用单引号或双引号将串和日期值括起来.上面例子中的N U L L值是用于student 和event 表中的A U TO_INCREMENT 列的.(插入"错误"的值将招致下一个student_id 或event_id 号的自动生成.)自3.22.5 以来的MySQL 版本答应通过指定多个值的列表,操纵单个的I N S E RT语句将几行插入一个表中,以下所示:
? ? 比方:
? ? 这比多个I N S E RT 语句的键入工作要少,并且服务器履行的效率也更高.
? ? ■ 可以给出要赋值的那个列,然后再列出值.这关于但愿成立只有几个列需求初始设置的记录是很有效的.
? ? 比方:
? ?自MySQL 3.22.5 以来,这种情势的I N S E RT 也允很多个值表:
? ? 在列的列表中未给出名称的列都将赋予缺省值.
? ? ■ 自MySQL 3.22 .10 以来,可以col_name = value 的情势给出列和值.
? ? 比方:
? ? 在SET 子句中未命名的行都赋予一个缺省值.利用这种情势的I N S E RT 语句不能插入多行.将记录装到表中的另一种办法是直接从文件读取数据值.可以用LOAD DATA 语句或用mysqlimport 实用程序来装入记录.LOAD DATA 语句起批量装载程序的作用,它从一个文件中读取数据.可在mysql 内利用它,以下所示:
? ? 该语句读取位于客户机被骗前目录中数据文件m e m b e r.txt 的内容,并将其发送到服务器装入member 表.假如您的MySQL 版本低于3 . 2 2 . 1 5,则LOAD DATA LOCAL 不起作用,因为当时从客户机读取数据的本领是在LOAD DATA 上的.(没有LOCAL 关键字,被读取的文件必须位于服务器主机上,并且需求大大都MySQL 用户都不具有的服务器拜候权限.)缺省时,LOAD DATA 语句假定列值由tab 键脱离,而行则以换行符完毕.还假定各个值是按列在表中的存放次序给出的.也有大概需求读取其他格局的文件,大概指定差别的列次
序.更具体的内容请参阅附录D的LOAD DATA 的条款.mysqlimport 实用程序起LOAD DATA 的号令行接口的作用.从外壳程序调用mysqlimport ,它生成一个LOAD DATA 语句:
? ? mysqlimport 生成一个LOAD DATA 语句,此语句使m e m b e r.txt 文件被装入member 表.假如您的MySQL 版本低于3 . 2 2 . 1 5,这个实用程序不起作用,因为--local 选项需求L O A DD ATA LOCAL.正如利用mysql 一样,假如您需求指定衔接参数,可在号令行上数据库名前指定它们.mysqlimport 从数据文件名中导出表名(它将文件名第一个圆点前的全部字符作为表名).比方,m e m b e r.txt 将被装入member 表,而president.txt 将被装入president 表.假如您有多个需求装入单个表的文件,应细心地挑选文件名,不然mysqlimport 将不能利用精确的表名.关于如像member1.txt 与member2.txt 这样的文件名, mysqlimport 将会认为呼应的表名为
member1 和m e m b e r 2.不过,可以利用如m e m b e r.1.txt 和m e m b e r.2.txt 或m e m b e r.txt1 和m e m b e r.txt2 这样的文件名.在试用过这些记录追加的办法后,应当排除各个表并重新装载它们,以便它们的内容与下一节假定的内容相同.从外壳程序履行下列号令:
? ? 每个文件都含有一个删除大概曾经插入到表中的记录的DELETE 语句,后跟一组INSERT 语句以初始化表的内容.假如不但愿辨别键入这些号令,可试一下下列语句:
? ? 1.4.8 检索信息
? ? 目前各个表已经成立并装有数据了,因此让我们来看看可以对这些数据做点什么.SELECT 语句答应以普通的或特别的方法检索和显示表中的信息.它可以显示表的整个内容:
? ? 大概只显示单个行中单个列的内容:
? ? SELECT 语句有几个子句(部件),可以按照需求用来检索感爱好的信息.每个子句都可简单、可复杂,从而SELECT 作为一个总的语句也繁简皆宜.但是,可以安心,本书中不会有花一个钟头来编写的长达数页的查询.(我在书中看到有很长的查询时,普通会当即跳过它们,因此我猜您也会这样.)SELECT 语句的普通情势为:SELECT 要挑选的东西FROM 一个或多个表WHERE 数据必须满意的条件记着,SQL 为一个安闲格局的语言,因此在您编写SELECT 查询时,语句的断行没必要严峻按照本书.
? ? 为了编写SELECT 语句,只需指定需求检索什么,然后再挑选某些子句便可.方才给出的子句" F R O M"、"W H E R E"是最常用的,还有一些其他的子句,如GROUP BY、O R D E RBY 和LIMIT 等.FROM 子句普通都要给出,但是假如不从表中挑选数据,也可不给出.比方,下列查询只显示某些可以直接计算而没必要引用任何表的表达式的值,因此不需求用FROM 子句:
? ? 在确切利用一个FROM 子句指定了要从此中检索数据的表时, SELECT 语句的最"普通"的格局是检索全部内容.用" *"来表示"全部列".下面的查询将从student 表中检索全部行并显示:
? ? 各列按它们MySQL 在表中存放的次序呈现.该次序与公布DESCRIBE student 语句时显示的列次序相同.(例子末尾的". . ."表示此查询返回的输出行比这里显示的还要多.)可明确地命名但愿得到的一列或多列.假如只挑选学生名,公布下列语句:
? ?假如名字不止一列,可用逗号脱离它们.下列的语句与SELECT * FROM student 等价,只是明确地指出了每一列:
? ? 可按肆意次序给出列:
? ?假若有必要,同一列乃至也可以给出多次,固然这样做普通是没有意义的.列名在MySQL 中不辨别大小写的.下面的查询是平等的:
? ?数据库和表名有大概辨别大小写的;这有取决服务器主机上利用的文件系统.在U N I X上运行的服务器对数据库名和表名是辨别大小写的,因为UNIX 的文件名是辨别大小写的.Windows 的文件名不辨别大小写,因此运行在Windows 上的服务器对数据库名和表名不辨别
大小写.MySQL 答应您一次从多个表中挑选列.我们将这个内容留到"从多个表中检索信息"小节去介绍.
? ?1. 指定检索条件
? ?为了限制SELECT 语句检索出来的记录集,可以利用WHERE 子句,它给出挑选行的条件.可通过查找满意各种条件的列值来挑选行.
?? 可查找数字值:
? ? 也可以查找串值.(注意,普通串的对比是不辨别大小写的.)
? ? 可以查找日期值:
? ? 可搜索组合值:
? ? WHERE 子句中的表达式可以利用表1-1 中的算术运算符、表1-2 的对比运算符和表1-3 的逻辑运算符.还可以利用圆括号将一个表达式分成几个部份.可以利用常量、表列和函数来完成运算.在本教程的查询中,我们有时利用几个MySQL 函数,但是MySQL 的函数远不止这里
给出的这些.请参阅附录C,那边给出了全部MySQL 函数的清单.
?? 在用表达式表示一个需求逻辑运算的查询时,要注意别混合逻辑与运算符与我们普通利用的"与"的含义.假定但愿查找"诞生在Vi rginia 的总统与诞生在Maryland 的总统".应当注意怎样表示"与"的关系,能写成以下的查询吗?
? ? 错了,因为这个查询的意思是"挑选既诞生在Vi rginia 又诞生在M a r y l a n d的总统",不大概有同时诞生在两个地址的总统,因此这个查询无意义.在英语中,可以用"a n d"表示这种挑选,但在SQL 中,应当用OR 来衔接两个条件,以下所示:
? ? 这有时是可以发觉到的,不但仅是在编写自己的查询时可以发觉到,并且在为他人编写查询时也可以知道.最好是在他人描写想要检索什么时细心听,但不一定利用相同的逻辑运算符将他人的描写转录成SQL 语句.对方才所举的例子,精确的英语等价描写为"挑选诞生在Vi rginia 大概诞生在Maryland 的总统."
? ? 2. NULL 值
? ? NULL 值是特别的;因为它代表"无值".不大概以评价两个已知值的相同方法来将它与已知值举行评价.假如试图与普通的算术对比运算符一道利用N U L L,后来果是未定义的:
? ??为了举行NULL 值的搜索,必须采取特别的语法.不能用= 或!= 来测试等于NULL 或不等于N U L L,取而代之的是利用IS NULL 或IS NOT NULL 来测试.比方,因为我们将健在总统的死亡日期表示为N U L L,那么可按以下语句查找健在的总统:
? ? MySQL3.23 及今后的版本具有一个特别的MySQL 专有的对比运算符" < = >",即便是NULL 与NULL 的对比,它也是可行的.用这个对比运算符,可将前面的两个查询重写为:
? ? 3. 对查询后果举行排序
? ? 有时我们注意到,在一个表装入初始数据后,对其公布一条SELECT * FROM tbl_name查询,检索出的行与这些行被插入的次序是相同的.但不要认为这种情形是有规律的.假如在初始装入表后举行了行的删除和插入,就会发现服务器返回表的行次序被改变了.(删除记录在表中留下了未利用的"空位",MySQL 在今后插入新记录时将会试图对其弥补.)缺省时,假如挑选了行,服务器对返回行的次序不作任何保证.为了对行举行排序,可
利用ORDER BY 子句:
? ? 在ORDER BY 子句中,可在列名之后操纵ASC 或DESC 关键字指定排序是按该列值的升序或降序举行的.比方,为了按倒序(降序)名布列总统名,可以下利用D E S C:
? ? 假如在ORDER BY 子句中,对某个列名既不指定ASC 又不指定D E S C,则缺省的次序为升序.在对大概包含NULL 值的摆列行排序时,假如是升序排序, NULL 值呈目前最前面,假如是按降序排序,NULL 值呈目前最后.
? ? 查询后果可在多个列上举行排序,而每个列的升序或降序可以彼此独立.下面的查询从president 表中检索行,并按诞生的州降序、在每个州中再按姓氏的升序对检索后果举行排序:
? ? 4. 限制查询后果假如一个查询返回很多行,但您只想看此中的几行,则可以操纵LIMIT 子句,分外是与ORDER BY 子句结合时更是如此.MySQL 答应限制一个查询的输出为前n 行.下面的查询挑选了5 位诞生日期最早的总统:
? ? 假如操纵ORDER BY birth DESC 按降序排序,将得到5 位最晚诞生的总统.LIMIT 也可以从查询后果中取出中间部份.为了做到这一点,必须指定两个值.第一个值为后果中但愿看到的第一个记录(第一个后果记录的编号为0 而不是1).第二个值为但愿看到的记录个数.下面的查询近似于前面那个查询,但只显示从第11 行开始的5 个记录:
? ? 自MySQL 3.23.2 以来,可按照一个公式来排序查询后果.比方,操纵ORDER BYRAND( ) 与LIMIT 结合,从president 表中随机抽取一个记录:
? ? 5. 计算并命名输出的列值
? ? 前面的大都查询通过从表中检索值已经产生了输出后果.MySQL 还答应作为一个公式的后果来计算输出列的值.表达式可以简单也可以复杂.下面的查询求一个简单表达式的值(常量)以及一个触及几个算术运算符和两个函数调用的较复杂的表达式的值:
? ? 此查询把名和姓衔接起来,中间隔断一个空格,将总统名形成一个单一字符串,并且将诞生城市和州衔接在一同,中隔断一个逗号,形成诞生地.
在操纵表达式来计算列值时,此表达式被用作列标题.假如表达式很长(如前面的一些查询样例中那样),那么大概会呈现一个很宽的列.为了处理这种情形,此列可操纵AS name构造来重新命名标题.这样的名称为列别名.用这种办法可以使上面的输出更有意义,以下所示:
? ? 6. 利用日期
? ?在MySQL 中利用日期时要记着的是,在表示日期时首先给出年份.1999 年7 月27 日表示为"1 9 9 9 - 0 7 - 2 7",而不是像普通那样表示为" 0 7 - 2 7 - 1 9 9 9"或"2 7 - 0 7 - 1 9 9 9".MySQL 供应了几种对日期举行处理的办法.可以对日期举行的一些运算以下:
? ?■ 按日期排序.(这点我们已经看到几次了.)
? ?■ 查找特定的日期或日期范围.
? ?■ 提取日期值的构成部份,如年、月或日.
? ?■ 计算日期的差.
? ?■ 日期增添或减去一个隔断得出另一日期.
? ?下面给出一些日期运算的例子.
? ?为了查找特定的日期,可以利用切确的日期值或与其另日期值举行对比,将一个D ATE 列与有关的日期值举行对比:
? ? 为了测试或检索日期的成份,可以利用诸如YEAR( )、MONTH( ) 或D AYOFMONTH( ) 这样的函数.比方,可通过查找月份值为3 的日期,找出与笔者诞生在相同月份(三月)的总统.
? ? 为了更具体,具体到天,可组合测试MONTH( ) 和D AYOFMONTH( ) 以找出在笔者的生日诞生的总统:
? ? 这是一种可用来生成近似报纸上娱乐部份所登载的那种"这些人本日过生日"清单的查询.但是,没必要按前面的查询那样插入一个特别的日期.为了查找每年的本日诞生的总统,只要将他们的生日与C U R R E N T _ D ATE 举行对比便可:
? ? 可从一个日期减去另一个日期.这样可以知道日期间的隔断,这关于肯定年纪是非常有效的.比方,为了肯定哪位总统活得最长,可将其去世日期减去诞生日期.为此,可操纵函数TO _ D AYS( ) 将诞生日期和去世日期转换为天数,求出差,然后除以365 得出大约的年纪:
? ? 此查询中所用的FLOOR( ) 函数截掉了年纪的小数部份,得到一个整数.得出日期之差,还可以肯定相关于某个特定日期有多长时间.这样可以奉告历史同盟的会员,他们还有多久就应当更新自己的会员资格了.计算他们的终止日期和当前日期之差,假如小于某个阈值,则不久就需求更新了.下面的查询是查找需求在60 天内更新的会员:
? ? 自MySQL 3.22 以来,可以利用D ATE_ADD( ) 或D ATE_SUB( ) 从一个日期计算另一个日期.这些函数取一个日期及时间隔断并产生一个新日期.比方:
? ?本节中前面给出的一个查询挑选70 年代去世的总统,它对挑选范围的端点利用直接的日期值.该查询可以操纵一个字符串日期和一个由开始日期和时间隔断计算出的完毕日期来重写:
? ? 会员更新查询可按照D ATE_ADD( ) 写出以下:
? ? 本章前面给出了一个查询以下,肯定不久要来查抄但还没来诊所的牙科病人:
? ? 目前回过头来看,读者会更清楚这个查询的含义了.
? ? 7. 情势匹配
? ? MySQL 答应查找与某个情势相配的值.这样,可以挑选记录而不用供应切确的值.为了举行情势匹配运算,可以利用特别的运算符( LIKE 和NOT LIKE),并且指定一个包含通配符的串.字符"_"匹配肆意单个字符,而"%"匹配肆意字符序列(包含空序列).利用L I K E或NOT LIKE 的情势匹配都是不辨别大小写的.下列情势匹配以"W"或"w"开始的姓:
? ? 此查询给出了一个常见的错误,它对一个算术对比运算符利用了情势.这种对比成功的惟一大概是呼应的列确切包含串" W %"或"w %".下列情势匹配肆意位置包含"W"或"w"的姓:
? ? MySQL 还供应基于扩大正规表达式的情势匹配.正规表达式在附录C 的REGEXP 运算符的介绍中描写.
? ? 8. 生成汇总
? ? MySQL 所能做的最有效的事情是浓缩大量的原始数据行并对其举行汇总.当学会了操纵MySQL 来生成汇总时,它就变成了用户强有力的好辅佐了,因为手工举行汇老是一项冗长的、费时的、易出错的工作.汇总的一种简单的情势是肯定在一组值中哪些值是唯一值.操纵DISTINCT 关键字来删除后果中的反复行.比方,总统诞生的各个州可按以下找出:
? ? 其他的汇总情势触及计数,可操纵COUNT( ) 函数.假如利用COUNT (*),它将给出查询所挑选的行数.假如一个查询无WHERE 子句,COUNT(*) 将给出表中的行数.下列查询给出共有多少人当过美国总统:
? ? 假如查询有WHERE 子句,COUNT(*) 将给出此子句挑选多少行.下面的查询给出目前为止对班级举行了多少次测试:
? ? COUNT(*) 对选中的行举行计数.而COUNT(col_name) 只对非NULL 值举行计数.下面的查询阐明了这些差别:
? ? 这表示,总共有41 位总统,他们中只有一个具闻名字后缀,并且大大都总统都已去世.自MySQL 3.23.2 以来,可以将COUNT( ) 与DISTINCT 组合对挑选后果集合差别的值举行计数.比方,为了对总统诞生的差别州举行计数,可履行下列查询:
? ? 可以按照汇总列中单独的值对计数值举行分化.比方,您大概按照下列的查询后果知道班级中全部学生的人数:
? ? 但是,有多少是男孩?有多少是女孩?辨别得出男孩、女孩的一种办法是辨别对每种性别举行计数:
? ? 固然这个办法可行,但是它很繁锁并且并不真正合适于大概有很多差别的值的列.考虑一下怎样以这种方法肯定每个州诞生的总统人数.您不得不找出有哪些州,从而不能省略(SELECT DISTINCT state FROM president),然后对每个州履行一个SELECT COUNT(*) 查询.很明显,有些事是可以简化的.所幸MySQL 可以操纵单个查询对一个列中差别的值举行计数.因此,针对学生表可以按以下得出男孩和女孩的人数:
? ? 假如以这种办法对值计数, GROUP BY 子句是必须的;它奉告MySQL 在对值计数之前怎样举行堆积.假如将其省去,则要出错.COUNT(*) 与GROUP BY 一同用来对值举行计数比辨别对每个差别的列值举行计数有更多的长处,这些长处是:
? ? ■ 没必要事前知道要汇总的列中有些什么值.
? ? ■ 不用编写多个查询,只需编写单个查询便可.
? ? ■ 用单一查询便可以得出全部后果,因此可以对后果举行排序.
前两个长处关于更便利地表示查询很重要.第三个长处也较为重要,因为它供应了显示
后果的机动性.在利用GROUP BY 子句时,后来果是在要分组的列上举行排序的,但是可以
利用ORDER BY 来按差别的次序举行排序.比方,假如想得到各州产生的总统人数,并按产
生人数最多的州优先排出,可以以下利用ORDER BY 子句:
? ? 假如但愿举行排序的列是从计算得出的,则可以给该列一个体名,并在ORDER BY 子句中引用这个体名.前面的查询阐明了这一点; COUNT(*) 列的别名为c o u n t.引用这样的列的另一种办法是引用它在输出后果中的位置.前面的查询可编写以下:
? ? 我不认为按位置引用列易读.假如增添、删除或重新排序输出列,必须注意查抄O R D E RBY 子句,并且假如列号改变后还得记着它.别名就不存在这种问题.假如想与计算出来的列一道利用GROUP BY,正如ORDER BY 一样,应当操纵别名或各位置来引用它.下面的查询肯定在一年的每个月中诞生的总统人数:
? ? 假如不想用LIMIT 子句来限制查询输出,而是操纵查找特定的COUNT( ) 值来到达这个目的,可以利用H AVING 子句.下面的查询给出了产生两个以上总统的州:
? ? 从更为广泛的意义上说,这是一种在要查找的列中反复值时履行的查询范例.H AVING 近似于W H E R E,但它是在查询后果已经选出后才利用的,用来缩减服务器实际送到客户机的后果.除了COUNT( ) 外还有很多汇总函数.MIN( )、MAX( )、SUM( ) 和AVG( ) 函数在肯定列的最大、最小、总数和平均值时都非常有效,乃至可以同时利用它们.下面的查询得出给定的测试和查验的各种数字特点.它还给出有多少学分参与了每个值的计算(有的学生大概缺旷或未计入).
? ? 当然,假如您知道这些信息是来自查验的还是测试的,则它们就会更有意义.但是,为了产生那样的信息,还需求参考event 表;我们将在下一节"从多个表中检索信息"谈论这个查询.汇总信息是很有意思的,因为它们是那么有效,但不太好掌握,简单走样.请看下列查询:
? ? 此查询挑选已经去世的总统,按诞生地对他们举行分组,并计算出他们去世时的年纪,计算出平均年纪(每个州的),然后按平均年纪举行排序.换句话说,此查询按所诞生地肯定已故总统的平均寿命.但这阐明了什么呢?它仅仅阐明您可写该查询,当然并不阐明此查询能否值得写.并非用一个数据库可以做的全部事情都一样有意义;但是,人们有时在发现可以操纵自己的数据库举行查询时感到很高兴.这大概阐明关于转播运动会的不断增添的高深的(空洞的)统计数据在过去几年里正在不断增添的缘由.运动统计者可以利用他们的数据库来计算出某个队的历史记录,而这些数字你大概感爱好,也大概毫无兴趣.
? ? 9. 从多个表中检索信息
? ? 到目前为止,我们所编写的查询都是从单个表中得到数据的.目前,我们将举行一件更为风趣的工作.从前笔者曾经提到过,关系DBMS 的强盛功效在于它可以将一样东西与另一样东西相关联,因为这样使得可以结合多个表中的信息来解答单个表不能解答的问题.本节介绍怎样编写这种查询.在从多个表中挑选信息时,需求履行一种称为衔接( j o i n)的操作.这是因为需求将一个表中的信息与其他表中的信息相衔接来得出查询后果.即通过调和各表中的值来完成这项工作.
? ? 我们来研究一个例子.在前面的"学分保存筹划"小节中,给出了一个检索特定日期的查验或测试学分的查询,但没有注释.目前可以举行注释了.这个查询实际触及到三种衔接办法,因此我们分两步举行研究.第一步,我们构造一个对特定日期的学分举行挑选的查询,以下所示:
? ?
? ? 此查询找出具有给定日期的记录,然后操纵该记录中的事件ID 查找具有相同事件ID 的学分.关于每个匹配的事件记录和学分记录组合,显示学生I D、学分、日期和事件范例.此查询在两个重要方面差别于我们曾经编写过的其他查询.它们是:
? ? ■ FROM 子句给出了不止一个表名,因为我们要检索的数据来自不止一个表:
????FROM event,score
????■ WHERE 子句阐明event 和score 表是由每个表中的event_id 值的匹配衔接起来的:
????where event.event_id=score.event_id
? ? 请注意,我们是怎样操纵tbl_name.col_name 语法引用列,以便MySQL 知道引用的是哪些表的列.(event_id 呈目前两个表中,假如不用表名来限定它的话将会呈现混合.)此查询中的其他列( d a t e、s c o r e、t y p e)可单独利用而不用表名限定符,因为它们在表中只呈现一次,从而不会呈现含糊.但是,普通在衔接中我们对每个列都举行限定以便清楚地表示出每个列是属于哪个表.在完好限定的情势下,查询以下:
? ? 从目前起,我们将利用完好限定的情势.第二步,我们操纵student 表完成查询以便显示学生名.(第一步中查询的输出给出了student_id 字段,但是名字更有意义.)名字显示是操纵score 表和student 表二者都具有student_id 列,使它们中的记录可被衔接这个事实来完成的.终究的查询以下:
? ? 此查询与前一个查询的差别在于:
? ? ■ student 表被增添到了FROM 子句中,因为除了event 表和score 表外还用到了它.
? ? ■ student_id 列目前不明确了(因为目前有两个引用到的表都含有此列),因此必须限定为score.student_id 或student.student_id 以表明利用的是哪个表.
? ? ■ WHERE 子句有一个附加项,它阐明按照学生ID 将score 表记录与student 表记录举行匹配.
? ? ■ 此查询是显示学生名而不是学生I D.(当然,假如乐意的话,可以二者都显示.)操纵此查询,可以加入肆意日期,得到该日期的学分,用学生名和学分范例完善查询后果.不一定要理解关于学生ID 或事件ID 的情形.MySQL 当心地得出相关的ID 值并操纵它们自动地使各表的行相配.
? ? 学分保存筹划触及的另一项工作是汇总学生的缺勤情形.缺勤情形是按学生ID 和日期在absence 表中记录的.为得到学生名(而不但仅是I D),我们需求按照student_id 的值将absence 表衔接到student 表.下面的查询给出了学生的ID 号和名字以及缺勤计数:
? ? 注意:固然我们在GROUP BY 子句中利用了一个限定符,但关于这个查询来说不是必须的.因为GROUP BY 子句只引用挑选表中(此查询的前两行)的列.在该处只有一个名为student_id 的列,因此MySQL 知道应当用哪个列.这个法则对ORDER BY 子句也成立.假如我们但愿只理解哪些学生缺过勤,则此查询所产生的输出也是有效的.但是,假如我们将此清单交给学校办公室,他们大概会说,"其他的学生呢?我们需求每个学生的情形."这是一个略微有点差别的问题.它表示需求知道学生的缺勤数,即便没有缺勤的学生也需求知道.因为问题的差别,查询也应当差别.
为了办理上述问题,利用LEFT JOIN 而不触及WHERE 子句中的学生I D.LEFT JOIN要求MySQL 对从衔接首先给出的表中挑选每行生成一个输出行(即LEFT JOIN 关键字左边给出的表).由于首先给出student 表,我们得到了每个学生的输出后果,即便是那些在absence 表中未给出的学生也都包含在输出中.此查询以下:
? ? 前面,在"生成汇总"一节中,我们履行了一个查询,它生成score 表中数据的数值特点.该查询的输出列出了事件I D,但不包含学分日期或范例,因为我们不知道怎样将score 表衔接到event 表以得到学分的日期和范例.目前可以做到了.下面的查询近似于早先的那个,但是它给出了学分的日期和范例而不只是简单的数字事件I D:
? ? 可操纵诸如COUNT( ) 和AVG( ) 这样的函数生成多个列上的汇总,即便这些列来自差别的表也是如此.下面的查询肯定学分数,以及事件日期与学生性别的每种组合的平均学分.
? ? 我们可以利用一个近似的查询来完成学分保存筹划的一个任务,即在学期末计算每个学生的总学分.呼应的查询以下:
? ? 不一定要求衔接必须用两个差别的表来完成.这仿佛有点奇特,但是确切可以将一个表衔接到其自身.比方,可通过针对每个总统的诞生地查看其他各个总统的诞生地,肯定几个总统能否诞生在相同城市.此查询以下:
? ? 此查询有两个本领性的东西:
? ? ■ 我们需求利用同一表的两个实例,因此成立了表的别名( p 1、p 2),并操纵它们无歧义地引用表列.
? ? ■ 每个总统的记录与自身相匹配,但是我们不但愿在输出中看到同一总统出再现两次.WHERE 子句的第二行保证对比的记录为差别总统的记录,使记录不与自身匹配.可以编写一个查找诞生在同一天的总统的近似查询.诞生日期不能直接对比,因为那样会错过诞生在差别年份的总统.我们用MONTH( ) 和D AYOFMONTH( ) 来对比诞生日期的月和日,呼应的查询以下:
??操纵D AYOFYEAR( ) 而不是MONTH( ) 和D AYOFMONTH( ) 将得出一个更为简单的查询,但是在对比闰年日期与非闰年日期时将会得出不精确的后果.迄今所履行的衔接结合了来自那些在某种意义上具有逻辑关系的表中的信息,但是只有您知道该关系无意义.MySQL 并不知道(或不关心)所衔接的表彼此之间能否相关.比方,可将event 表衔接到president 表以找出在某个总统生日那天能否举行了查验或测试,此查询以下:
? ? 它产生了您所想要的东西.但阐明了什么呢?这阐明MySQL 将高兴地制造出后果,至于这些后果能否有意义它不管.这是因为您利用的是计算机,所以它不能自动地判断查询的后果有效或无用.无论若何,我们都必须为自己所做的事负责.
以上是“MySQL数据库技术(04)[MySQL防范]”的内容,如果你对以上该文章内容感兴趣,你可以看看七道奇为您推荐以下文章:
本文地址: | 与您的QQ/BBS好友分享! |