SQL学习指南(第2版)(修订版)

978-7-115-38344-0
作者: 【美】Alan Beaulieu
译者: 张伟超 林青松
编辑: 陈冀康

图书目录:

详情

本书涉及不同平台上数据的排序、过滤和分组,以及表、视图、联结、子查询、游标、存储过程和触发器等内容,通过本书读者可以系统地学习到SQL 的知识和方法。本书包含许多原则或准则,并通过举例的方式对原则进行解释说明。本书注重实用性,操作性很强,适合于SQL 的初学者学习和广大软件开发及管理人员参考。

图书摘要

版权信息

书名:SQL学习指南(第2版)(修订版)

ISBN:978-7-115-38344-0

本书由人民邮电出版社发行数字版。版权所有,侵权必究。

您购买的人民邮电出版社电子书仅供您个人使用,未经授权,不得以任何方式复制和传播本书内容。

我们愿意相信读者具有这样的良知和觉悟,与我们共同保护知识产权。

如果购买者有侵权行为,我们可能对该用户实施包括但不限于关闭该帐号等维权措施,并可能追究法律责任。

• 著    [美] Alan Beaulieu

  译    张伟超 林青松

  责任编辑  陈冀康

• 人民邮电出版社出版发行  北京市丰台区成寿寺路11号

  邮编 100164  电子邮件 315@ptpress.com.cn

  网址 http://www.ptpress.com.cn

• 读者服务热线:(010)81055410

  反盗版热线:(010)81055315

Copyright©2009 by O’Reilly Media, Inc.

Simplified Chinese Edition, jointly published by O’Reilly Media, Inc. and Posts & Telecom Press, 2010. Authorized translation of the English edition, 2009 O’Reilly Media, Inc., the owner of all rights to publish and sell the same.

All rights reserved including the rights of reproduction in whole or in part in any form.

本书中文简体版由O’Reilly Media, Inc.授权人民邮电出版社出版。未经出版者书面许可,对本书的任何部分不得以任何方式复制或抄袭。

版权所有,侵权必究。


本书全面系统地介绍了SQL语言各方面的基础知识以及一些高级特性,包括SQL数据语言、SQL方案语言、数据集操作、子查询以及内建函数与条件逻辑等内容。书中每个章节讲述一个相对独立的主题,并提供了相关示例和练习。本书内容以SQL 92标准为蓝本,涵盖了市场上常用数据库的最新版本(MySQL 6.0、Oracle 11g及Microsoft SQL Server 2008)。

本书适合数据库应用开发者、数据库管理员和高级用户阅读。针对开发基于数据库的应用程序,以及日常的数据库系统管理,本书都展现了大量经过实践检验的方法和技巧。读者可以通过对本书循序渐进地学习快速掌握SQL语言,也可以在实际工作中遇到问题时直接翻阅本书中的相关章节以获取解决方案。


为了满足你对网络和软件技术知识的迫切需求,世界著名计算机图书出版机构O’Reilly Media, Inc.授权人民邮电出版社,翻译出版一批该公司久负盛名的英文经典技术专著。

O’Reilly Media, Inc.是世界上在 UNIX、X、Internet 和其他开放系统图书领域具有领导地位的出版公司,同时也是联机出版的先锋。

从最畅销的The Whole Internet User’s Guide & Catalog(被纽约公共图书馆评为20世纪最重要的50本书之一)到GNN(最早的Internet门户和商业网站),再到WebSite(第一个桌面PC的Web服务器软件),O’Reilly Media, Inc.一直处于Internet发展的最前沿。

许多书店的反馈表明,O’Reilly Media, Inc.是最稳定的计算机图书出——商—每一本书都一版再版。与大多数计算机图书出版商相比,O’Reilly Media, Inc.具有深厚的计算机专业背景,这使得O’Reilly Media, Inc.形成了一个非常不同于其他出版商的出版方针。O’Reilly Media, Inc.所有的编辑人员以前都是程序员,或者是顶尖级的技术专家。O’Reilly Media, Inc.还有许多固定的作者群体——他们本身是相关领域的技术专家、咨询专家,而现在编写著作,O’Reilly Media,Inc.依靠他们及时地推出图书。因为O’Reilly Media, Inc.紧密地与计算机业界联系着,所以O’Reilly Media, Inc.知道市场上真正需要什么图书。


编程语言在不断地出现和消亡,现在使用的语言只有很少一部分的历史能追溯到20年前。其中有大量应用在大型机环境的Cobol和流行于操作系统、服务器开发以及嵌入式系统的C语言。而在数据库领域,SQL的根源可以追溯到19世纪70年代。

SQL是一种从关系型数据库生成、操作和检索数据的语言。关系型数据库流行的原因之一是正确设计的关系型数据库可以处理海量数据。但处理大量数据集时,SQL就像一个高功率可变焦距的时髦数码相机,让你能够看到大型数据集,或者放大单独的行(或者两者之间的任何地方)。其他的数据库管理系统在沉重的负荷下往往会由于它们的焦距太窄(缩放镜头已经处于最大位置了)而崩溃,这就是要废黜关系型数据库和SQL的尝试已经基本上失败了的原因。因此,即使SQL是一门古老的语言,它也将继续活跃很长一段时间,并且在存储应用方面有光明的前途。

如果打算使用关系型数据库,无论是写应用程序、执行管理任务还是生成报表,那么都需要知道如何与数据库中的数据交互。即使使用工具为自己生成SQL,比如报表工具,有时也需要绕过自动生成功能而编写自己的SQL语句。

学习SQL语言有一个额外的好处,即强迫你勇敢面对并学会理解用于储存自己组织相关信息的数据结构。当开始适应数据库的表时,你可能会发现自己也会产生对数据库进行修改或增加等的建议。

SQL语言可分为几类:用于创建数据库对象(表、索引、约束等)的语句统称为SQL模式语句,而用于创建、操纵和检索保存在数据库中的数据的语句称为SQL数据语句。作为管理员,你将同时使用SQL模式和SQL数据语句,而程序员或者报表作者可能只需要使用(或者只允许使用)SQL数据语句。虽然本书介绍了许多SQL模式语句,但是主要焦点还是编程功能。

由于只有少数命令,因此SQL数据语句看似很简单。依我看来,现在许多SQL图书都通过仅仅涉猎这个语言可能的表层知识帮助你培养这种观念。然而,如果打算使用SQL,那么你就有必要充分理解它的语言能力以及如何组合不同的功能以产生强大的结果。我感觉本书是唯一一本详细介绍SQL语言而不会同时被作为门挡的书(正如我知道的,1250页的“完全手册”往往被丢在人们的卧室书架上,布满了灰尘)。

虽然本书的示例都可以运行在MySQL、Oracle数据库以及SQL Server上,但是我必须选择其中之一来作为示例数据库服务器并规范化示例查询返回的结果集。我在这3个产品中选择了MySQL,是因为它可以免费获得、安装简单以及易于管理。对于那些使用其他服务器的人,我建议下载和安装MySQL并加载示例数据库,这样就可以运行示例数据库并试验数据了。

本书分为15章和3个附录。

第1章“背景知识”,探讨计算机数据库的历史,其中包括关系模型以及SQL语言的出现。

第2章“创建和操作数据库”,说明如何创建本书示例使用的MySQL数据库和表,以及用数据填充表。

第3章“查询入门”,介绍选择语句,然后进一步阐述了大多数常用子句(select、from、where)。

第4章“过滤”,说明不同类型的条件,它们可以用于select、update或delete语句的where子句中。

第5章“多表查询”,展示如何通过表的连接使用多表进行查询。

第6章“使用集合”,介绍所有关于数据集的知识以及它们如何在查询内交互。

第7章“数据生成、转换和操作”,说明用于操作或转换数据的几个内置函数。

第8章“分组与聚集”,展示如何聚合数据。

第9章“子查询”,介绍子查询(个人最喜欢的),并说明如何以及在何处使用它们。

第10章“再谈连接”,更加深入地讨论不同类型的表连接。

第11章“条件逻辑”,探讨如何在select、insert、update和delete语句里使用条件逻辑(如if-then-else)。

第12章“事务”,介绍事务及如何使用它们。

第13章“索引和约束”,探讨索引和约束。

第14章“视图”,说明如何构建接口以屏蔽数据复杂性。

第15章“元数据”,说明数据字典的使用。

附录A“示例数据库的ER图”,展示本书所有示例的数据库模式。

附录B“MySQL对SQL语言的扩展”,说明在MySQL的SQL实现中一些有趣的非ANSI功能。

附录C“练习答案”,介绍各章习题的答案。

本书使用了下面的印刷约定:

提示 

指出提示、建议或者一般注意性的问题。例如,我使用注意向你表明Oracle 9i的新功能。

警告

指示一个告诫或提醒。例如,我告诉你如果不小心使用,那么有些SQL语句可能会产生意想不到的后果。

请将对本书的评论和问题按以下地址与出版社联系。

美国:O’Reilly Media, Inc.

1005 Gravenstein Highway North

Sebastopol, CA 95472

中国:100035北京市西城区西直门成铭大厦C座807室

奥莱利技术咨询(北京)有限公司

O’Reilly为本书维护了一个网页,列出了勘误表、范例以及任何其他信息。可以通过以下地址访问:

http://www.oreilly.com/catalog/9780596520830

要询问技术问题或提出建议,请发邮件至:

bookquestions@oreilly.com

info@mail.oreilly.com.cn

更多关于O’Reilly的图书、会议信息、资源中心以及O’Reilly网络,请访问以下网页:

http://www.oreilly.com

http://www.oreilly.com.cn

本书是为了帮助你完成工作。一般情况下,你可以在程序和文档中使用本书的代码。如果你使用本书的重要代码,不必联系我们获取许可。例如,使用本书中几大块代码写自己的程序不需要获得许可,但是如果要将O’Reilly书籍中的用例制作成光盘出售或发布,则必须获得许可。引用本书内容或范例解决其他问题不需要获得许可,但是如果想在你的产品文档中包含本书中一些重要的示例代码,那么也需要得到许可。

如果引用了本书内容,那么我们很感激你标明出处,但并不做要求。出处通常包括标题、作者、出版商以及ISBN。例如,“Learning SQL, Second Edition, by Alan Beaulieu. Copyright 2009 O’Reilly Media, Inc., 978-0-596-52083-0.”。

如果你并不清楚使用本书示例代码是否侵权,请随时与我们联系:

permissions@oreilly.com

首先我想感谢编辑Mary Treseler,因为她的帮助使第2版成为现实,其次,再次感谢Kevin Kline、Roy Owens、Richard Sonen和Matthew Russell,是他们在圣诞节和新年时还在审查本书。我还想感谢第1版的一些读者,他们提出了很多问题、建议和勘误。最后,感谢我的妻子Nancy、女儿Michelle和Nicole,是她们给了我很多鼓励和启发。


Alan Beaulieu从事设计、构建和实现应用数据库已有15个年头,他目前经营自己的顾问公司,专门提供金融和电信领域的Oracle数据库设计与支持服务。Alan使用了Oracle的诸多特性,如并行查询、分区和并行服务器等,以构建OLTP和OLAP环境下的大型数据库。Alan获得了康奈尔大学工程学院的运筹学学士学位,现在和妻子以及两个女儿一起住在马萨诸塞州,可以通过电子邮箱albeau_mosql@yahoo.com与他联系。


本书封面上的动物是安第斯有袋树蛙,它的名字暗示了这种在傍晚和夜间活动的青蛙原生地在安第斯山脉的西坡,并且广泛分布在北部的里奥班巴盆地和伊瓦拉之间。

在求偶期,雄蛙发出“哇可-啊可-啊可”的叫声以吸引雌蛙,如果一只怀孕中的雌蛙被吸引过来,雄蛙将会爬到它的背上执行常见的青蛙交配过程。当雌蛙从泄殖腔中排出卵时,雄蛙用脚抓住这些卵并完成受精,然后将它们放到雌蛙的孵化袋中。雌蛙一次可以孵化130多枚蛙卵,这些卵需要在它的孵化袋中发育60~120天。 在孵化期间,雌蛙的身体将会变得臃肿,并且在它背部皮下将会出现许多肿块。当卵在孵化袋中发育成蝌蚪时,雌性树蛙将它们放入水中。两三个月之后,这些蝌蚪将会变成青蛙,而在7个月之后,它们进入了生育期,又开始“哇可-啊可-啊可”了。

雄性和雌性树蛙的前后趾上都进化出许多吸盘,这可以用来帮助它们攀爬树木等垂直的表面。成年雄蛙大小为2英寸左右(约5cm),而雌蛙为2.5英寸(6.35cm)。它们的表皮有时为绿色,有时为褐色,有时为这两种颜色的混合色,幼年期的树蛙在生长时会逐渐由褐色变为绿色。

封面图片来自于Dover Archive Pictorial(《多佛尔档案画报》)。


在我们开始学习本书的内容时,先了解一些数据库方面的基本概念及计算机数据存储和检索的发展史是十分有益的。

“数据库”是指一组相关信息的集合。例如,电话簿就可以被视为包含某地区所有居民的姓名、电话号码、地址等信息的数据库。尽管电话簿可能是一个最为普及和常用的数据库,但它仍有不少缺点,比如:

电话簿的这些缺陷同样存在于任何人工编制的数据存储系统,比如存放在档案柜的病历等。由于这些纸质数据库不方便,因此最早的计算机应用之一就是开发数据库系统,即通过计算机来存储和检索数据的机制。因为数据库系统通过电子而不是纸质方式来存储数据,所以它可以更快速地检索数据、以多种方式索引数据以及为其用户群提供最新的信息。

早期的数据库系统将被管理的数据存储在磁带上。一般情况下磁带的数量比磁带机要多得多,因此在请求数据时需要技术人员手动装卸磁带。同时由于那个时代的计算机内存很小,通常对同一数据的并发请求必须多次读取磁带,降低了使用效率。因此尽管这些数据库系统相对于纸质数据库有了显著的进步,但与今天的数据库技术相比仍有相当遥远的差距。(现代数据库系统能够利用海量快速的磁盘驱动器来管理太字节级的数据,在高速内存中存放数十吉字节的数据。)

提示 

本小节讨论早期非关系数据库的背景信息,如果读者急于学习SQL,可以跳过下面几页,直接阅读下一章节。

在计算机数据库发展的前几十年里,数据以各种不同的方式存储并展现给用户。例如,在层次数据库系统中,以一个或多个树形结构来表示数据。图1-1显示了以树形结构表示的George Blake和Sue Smith的银行账户数据。

图1-1 账户数据的层次视图

George和Sue的数据树都包含了各自的账户以及交易信息。层次数据库系统提供了定位客户信息树的工具,并能够遍历此树找到所需要的账户或交易数据。树中的每个节点都具有0个或1个父节点,以及0个、1个或多个子节点。这种设置被称为单根层次结构(single-parent hierarchy)。

另一种管理数据的方式是网状数据库系统,它表现为多个记录集合,集合之间通过链接来定义不同记录间的关系。图1-2显示了使用此系统表示的George和Sue的账户信息。

在此系统中,为了查找Sue的MoneyMkt账户上的交易信息,需要执行下面的步骤:

1.查找Sue Smith的客户记录;

2.通过链接从Sue Smith的客户记录找到其账户列表;

3.遍历账户列表直至找到MoneyMkt账户;

图1-2 账户数据的网状视图

4.通过链接从MoneyMkt账户找到其交易列表。

网状数据库系统的有趣特性体现在图1-2中最右侧的products记录。注意每个product记录(Checking、Savings等)都指向一个account记录列表,以指定这些账户记录的产品类型。因此account记录可以通过多个入口进行访问(customer记录或product记录),这使得网状数据库具有多根层次的特点。

层次和网状数据库仍然存在,尽管主要在大型机领域中使用。此外,层次数据库系统与可扩展标记语言(XML)相结合,在目录服务方面获得了新的应用,比如Microsoft公司的Active Directory和Red Hat的Directory Server。然而,从20世纪70年代开始,一种新的表示数据的方式逐步扎根并获得发展,这种方式更为严谨,且易于理解和实现。

1970年,IBM研究院的E.F.Codd博士发表了一篇名为“大型共享数据银行的数据关系模型”的论文,提出使用表集合来表示数据,但相关条目之间并不使用指针来导航,而是借助冗余数据来链接不同表中的记录。图1-3显示了此方法所表示的George和Sue的账户信息。

图1-3 账户数据的关系视图

图1-3中包含了4个记录表:Customer、Product、Account和Transaction。首先查看图中顶部的Customer表,其中具有3列:cust_id(其中包含客户的ID号)、fname(其中包含客户的名字)和lname(其中包含客户的姓氏)。Customer表中包含了两个记录行,分别为Georage Blake和Sue Smith的数据。在不同的数据库管理服务器中,记录表可包含的最大列数是有差异的,但通常这个数目足够大而不需要为此担心(比如Microsoft的SQL Server允许每张表可以最多具有1024列)。表中数据行的数目通常只是受到物理设备(磁盘空间大小)和可维护性(在表中记录数在到达多大规模之后仍能保持易用性)的限制,而数据库管理服务器一般不对此进行限制。

关系数据库中的每张表都包含一项作为每行唯一标识的信息(主键),它与其他信息一起构成了对条目的完整描述。对于Customer表,cust_id列为每个顾客保存了不同的编号。例如,George Blake可以由顾客 ID#1来唯一标识,其他顾客则永远不会被赋予此标识符。因此在Customer表中,不再需要其他信息来定位George Blake的数据。

提示 

每种数据库服务器都提供用于产生一组作为主键值的唯一数字的机制,因此用户不需要为哪些数字已被赋予为主键而操心。

当然也可以选择联合使用fname和lname两列作为主键(包含两列或多列的主键通常被称为复合主键),实际上,在银行账户中很可能会出现两个或多个人具有完全相同的姓氏和名字。因此,选择cust_id列专门用于Customer表的主键是更合适的做法。

提示

在本例中,选择fname/lname作为主键,称之为自然主键;使用cust_id作为主键,则称为逻辑主键。使用哪一种主键更好一直是悬而未决的热门讨论问题,但在本例中的选择是显而易见的,因为人们的姓名可能发生改变(比如某人结婚后使用其配偶的姓氏),而主键列在被赋值后是绝不允许被修改的。

一些表中还包含了导航到其他表的信息,即前文提到的“冗余数据”。举例来说,Account表中的cust_cd列,它包含了使用该账户的顾客的唯一性标识,而product_id列则包含了该账户所关联产品的唯一性标识。这些列被称为外键,用于作为账户信息网络结构中的各实体之间的连线。如果需要查询某个账户所有者的相关信息,则需要获取cust_id列的值,并使用它在Customer表中查找相应的行(在关系数据库术语中,此过程被称为连接(join),在第3章基本查询对此进行了介绍,并在第5章和第10章进行了更深入的讨论)。

也许多次存储同样的信息是一种浪费的做法,但是某些情况下使用冗余数据能够更清晰地体现关系模型。例如,在Account表中包含一个该账户所有者的唯一标识符是合适的,如果在Account表中再增加顾客的fname/lname列就不太恰当了,这会使数据库中的数据不再可靠。因为放置该数据(顾客的姓/名)的地方应当是Customer表,并且该表中只有cust_id列才适合在其他表中被引用。此外,在一列中包含多条信息也是不合适的,比如使用name列同时包含顾客的姓和名,或者使用address列包含街道、城市、省以及邮政编码等信息。数据库设计精化过程的主要目标就是保证每条独立的信息只存放在一个地方(外键除外),称为规范化。

返回到图1-3中的4个表,或许你会疑惑如何使用这些表来查找George Blake在他的checking账户上的交易信息。首先,在Customer表中找到George Blake的唯一性主键。然后,在Account表中找到cust_id列等于George的唯一性标识符,并通过Product_cd匹配Product表中name列为“Checking”的那些行。最后,通过匹配Account表的唯一性标识account_id列来定位Transaction表中相对应的行。这些看起来有些复杂,但你很快就会发现,在SQL语言中,使用一个命令就足以完成这些任务了。

在前面已经介绍了一些新的术语,下面介绍一些正式的定义,表1-1显示了本书余下部分所使用术语的定义。

表1-1 术语和定义

术语

定  义

实体

数据库用户所关注的对象,如顾客、部门、地理位置等

存储在表中的独立数据片段

所有列的一个集合,完整地描述了一个实体或实体上的某个行为,也称之为记录

行的集合,既可以保存在内存中(未持久化),也可以保存在存储设备中(已持久化)

结果集

未持久化表的另一个名字,一般为SQL查询的结果

主键

用于唯一标识表中每个行的一个或多个列

外键

一个或多个用于识别其他表中某一行的列

根据Codd对关系模型的定义,他提出一种名为DSL/Alpha的语言,用于操控关系表的数据。在Codd的论文发表后不久,IBM建立了一个研究小组来根据他的想法构建原型。该小组创建了一个DSL/Alpha的简化版本,即SQUARE,然后通过对SQUARE的改进,将之发展为SEQUEL语言,并最终命名为SQL。

今天SQL已经发展到了中年期(唉,就像作者一样),在这期间它经历了大量修改。在20世纪80年代中期,美国国家标准组织(ANSI)开始制定SQL语言的第一个标准,并于1986年发布。其后不断对其改进,并在1989年、1992年、1999年、2003年和2006年发布了一系列SQL标准的新版本。通过对语言核心的改良,新的特性被陆续加入到SQL语言中,以吸收面向对象等其他功能。最后一个标准版本,SQL 2006则聚焦于SQL和XML的集成,并定义了XQuery语言以用于在XML文档中查询数据。

SQL与关系模型的关系密切,因为SQL查询的结果也可以视为一张表(在程序上下文中称之为结果集)。因此,可以在关系数据库中简单地创建一个固定表,用于存放查询的结果集。同样地,SQL查询也可以使用固定表或其他查询的结果集作为其输入(在第9章中将会讲述其细节)。

最后需要注意的一点是:SQL并不是任何短语的缩写(尽管许多人坚持认为它代表结构化查询语言(Structured Query Language))。当提到此语言时,可以使用独立的字母(S.Q.L)或使用单词sequel。

在本书中,将分别讨论SQL语言的几个独立模块,即SQL 方案(schema)语句,用于定义存储于数据库中的数据结构;SQL数据语句,用于操作SQL方案语句所定义的数据结构;以及SQL事务语句,用于开始、结束或回滚事务(将在第12章中介绍)。例如,在数据库中创建新表时,需要使用SQL方案语句create table,而在新表中产生数据则需要SQL数据语句insert。

下面给出这些语句的具体例子,用于创建corporation表的SQL方案语句如下:

CREATE TABLE corporation
 (corp_id SMALLINT,
 name VARCHAR(30),
 CONSTRAINT pk_corporation PRIMARY KEY (corp_id)
 );

该语句创建的表包括两列:corp_id和name。其中,corp_id列被设置为表的主键。在第2章中,将会介绍该语句的细节,比如MySQL中所提供的各种数据类型。下面给出的SQL数据语句将向corporation表中插入一行关于Acme Paper Corporation的数据:

INSERT INTO corporation (corp_id, name)
VALUES (27,’Acme Paper Corporation’);

该语句向corporation表中添加了一行数据,其中corp_id列的值为27,而name列的值是Acme Paper Corporation。

最后,给出一条简单的select语句,以获取刚才创建的数据:

mysql> SELECT name
   -> FROM corporation
   -> WHERE corp_id = 27;
+------------------------+
| name            |
+------------------------+
| Acme Paper Corporation |
+------------------------+

通过SQL方案语句所创建的所有数据库元素都被存储在一个特殊的表集合,即数据字典中。这些“关于数据库的数据”一般被称为“元数据”,本书第15章将对此进行详细介绍。与用户所创建的表一样,数据字典表也可以通过select语句查询,从而允许在运行时刻查看数据库中的当前数据结构。例如,用户需要编写显示上月新增账户的报表,那么既可以在报表中对account表的各个列名进行硬编码,也可以通过查询数据字典以获取当前的列集合并在每次运行时动态地创建报表。

本书中的大部分篇幅将聚焦于SQL语言中的数据相关部分,包括select、update、insert和delete命令。SQL方案语句将在第2章中说明,并且该章所创建的示例数据库将在全书中使用。一般来说,不需要对SQL方案语句的语法进行太多论述,而对于SQL数据语句,尽管只有寥寥几条,但其中包含了大量值得仔细研究的内容。因此,尽管我尽量介绍更多的SQL方案语句,但本书的大多数章节还是把重点放在SQL数据语句上。

如果读者有过编程语言的使用经验,可能习惯于定义变量或数据结构、使用条件逻辑(即if-then-else)和循环结构(即do-while-end),并将程序代码分成可复用的小片段(如对象、函数、过程等)。这些代码经过编译后执行,其执行结果精确地(也并不是总是精确)符合编程的预期。无论是使用Java、C#、C、Visual Basic还是其他过程化语言,都可以完全控制程序的行为。

提示

过程化语言对所期望的结果和产生这些结果的执行机制或过程都进行了定义。非过程化语言同样定义了期望结果,但将产生结果的过程留给外部代理来定义。

使用SQL意味着必须放弃对过程的控制,因为SQL语句只定义必要的输入和输出,而执行语句的方式则交由数据库引擎的一个组件,即优化器(optimizer)处理。优化器的工作包括查看SQL语句并考虑该表的配置信息以及有无索引等,以确定最具效率的执行路径(当然,并不总是最有效率)。大多数数据库引擎允许通过指定优化器选项来影响优化器的决策,比如建议使用特定的索引等。而大多数SQL的用户并不需要考虑这个复杂的层面,而是将之交给数据库管理员或性能调优专家来处理。

因此单独使用SQL并不能开发完整的应用,除了编写简单的脚本来处理某些数据,一般需要将SQL与编程语言相集成。一些数据库厂商已经为用户考虑了这些,如Oracle的PL/SQL语言,MySQL的存储过程语言,以及Microsoft的Transact-SQL语言。在这些语言中,SQL数据语言是其语法的一部分,以准确无误地将数据库查询与过程化命令集成到一起。如果使用非数据库指定的语言,如Java等,则需要使用工具集/API以在代码中执行SQL语句。有些工具集由数据库厂商提供,其他的则由第三方厂商或开源代码提供者所创建。表1-2显示了将SQL集成到特定语言的可用选项。

表1-2 SQL集成工具集

语言

工 具 集

Java

JDBC (Java Database Connectivity; JavaSoft)

C++

Rogue Wave SourcePro DB (third-party tool to connect to Oracle, SQL Server, MySQL, Informix, DB2, Sybase, and PostgreSQL databases)

C/C++

Pro*C (Oracle), MySQL C API (open source), and DB2 Call Level Interface (IBM)

C#

ADO.NET (Microsoft)

Perl

Perl DBI

Python

Python DB

Visual Basic

ADO.NET (Microsoft)

如果用户仅仅需要执行交互式的命令,那么每种数据库开发商都提供了至少一个简单的命令行工具,用于向数据库引擎提交SQL命令。大多数开发商都提供了图形化的工具,其中包含显示SQL命令的窗口以及另一个显示SQL命令执行结果的窗口。因为本书中的例子都将在MySQL数据库中运行,所以本书使用mysql命令行工具。该工具属于MySQL安装文件的一部分,并用于运行示例和格式化的结果。

在本章前面,我说过要演示返回George Blake的checking账户上所有交易的SQL语句,下面就兑现这个承诺,语句和查询结果如下:

SELECT t.txn_id, t.txn_type_cd, t.txn_date, t.amount
FROM individual i
 INNER JOIN account a ON i.cust_id = a.cust_id
 INNER JOIN product p ON p.product_cd = a.product_cd
 INNER JOIN transaction t ON t.account_id = a.account_id
WHERE i.fname = 'George' AND i.lname = 'Blake'
 AND p.name = 'checking account';
+--------+-------------+---------------------+--------+
| txn_id | txn_type_cd | txn_date        | amount |
+--------+-------------+---------------------+--------+
|   11  | DBT      | 2008-01-05 00:00:00 | 100.00 |
+--------+-------------+---------------------+--------+
1 row in set (0.00 sec)

此处仅对此语句进行简单的分析:该查询查找满足下面两个条件的行,即在individual表中姓名为George Blake的行,以及在product表中的账户名为checking account的行,并通过account表将它们关联起来,然后返回transaction表中所有提交到该账户上的交易信息内容,并分4列显示。如果刚好知道George Blake的客户ID是8并且checking账户的指定代码为“CHK”,就可以简单地根据客户ID找到George Blake在account表中的checking账户,并使用账户ID来查找相关的交易:

SELECT t.txn_id, t.txn_type_cd, t.txn_date, t.amount
FROM account a
 INNER JOIN transaction t ON t.account_id = a.account_id
WHERE a.cust_id = 8 AND a.product_cd = 'CHK';

在下面的各章节里,将会覆盖到这些查询的所有概念(并且会涉及得很多),但在这里至少需要展示一下它们的大致结构。

前面的查询包含了3个不同的字句,包括select、from和where。几乎所有的查询都至少会包含这3个子句,当然还有其他几个子句可用于更特定的查询目标。下面展示了这3个子句所起的角色:

SELECT /* 1个或多个事物*/ ...
FROM /* 1个或多个地点*/ ...
WHERE /* 1个或多个条件*/ ...

提示

大多数的SQL实现都将/*和*/标记之间的文本视为注释。

当用户构造查询时,首先需要确定查找的是哪一个或哪些表,并将它们加入from子句中,然后在where子句中增加查询条件以过滤掉并不感兴趣的数据。最后,需要确定从各个表中所应提取的列,并将之增加到select子句中。下面给出一个简单的例子,以展示如何找到所有姓为“Smith”的客户:

SELECT cust_id, fname
FROM individual
WHERE lname = 'Smith';

该查询搜索individual表,以找到所有lname列匹配字符串'Smith'的行,并返回这些行中的cust_id和fname列。

除了查询数据库,还需要在数据库中建立和修改数据,下面举出一个简单的例子,以说明如何在product表中插入新行:

INSERT INTO product (product_cd, name)
VALUES ('CD', 'Certificate of Depysit')

糟糕,这里将“Deposit”拼错了,不过没有关系,可以使用update语句来修复这个错误:

UPDATE product
SET name = 'Certificate of Deposit'
WHERE product_cd = 'CD';

注意,与select语句一样,update语句也包含了where子句,这是因为update语句也要识别所需修改的行。在本例中,只需要将要修改的行指定为product_cd列与字符串'CD'相匹配的那些行即可。由于product_cd列是product表的主键,因此可以预计update语句会精确地修改某一行(或零行,如果表中该值不存在)。在任何时刻执行SQL数据语句,都会收到一个来自数据库引擎的反馈,以显示该语句所影响的行数。如果使用交互式工具,比如上文提到的mysql命令行工具,那么可以接收到下面几种操作所影响行数的反馈:

可以使用过程化语言,并结合上文提到的工具集来调用SQL语句。工具集通常包含了能够获取SQL数据语句执行信息的调用。一般来说,好的做法应当是检查这个信息以确信语句执行并没有超出预料(比如忘记为delete语句增加where子句,从而删除了表中的所有行)。

商业级关系数据库已经存在20多年了,几种最成熟和流行的商业产品包括:

这些数据库服务器的功能十分类似,尽管它们中的一些擅长处理大容量和高流量的数据库,而另一些对于处理对象、大文件或XML文档等更为适合,所有这些服务器都遵从了最新的ANSI SQL标准。这是一件好事,本书将演示如何编写标准的SQL语句,以便无须修改(或极少量的修改)就能够在这些平台中运行。

在最近5年里,除了商业级数据库服务器,开源社区也为创建商业数据库产品的可替代品而努力,其中两个最常用的开源数据库服务器为PostgreSQL和MySQL。MySQL的主页上(http://www.mysql.com)声称其已经拥有超过1000万次的安装,它的服务器版式是免费使用的,并且该服务器软件的下载和安装都非常简单。出于这些理由,本书的所有示例都将在MySQL(6.0版)上运行,并使用mysql命令行工具格式化查询结果。即使你已经使用了另一种数据库且从未打算使用MySQL,本书还是建议安装MySQL服务器的最新版本,并载入书中示例所包含的SQL方案和数据语句。

不过,读者还需要牢记下面的说明:

本书并不是一本MySQL的SQL实现教程。

事实上,本书原意是希望教授如何设计SQL语句并使之无需修改地运行在MySQL上,并能在无需或仅需要极少量修改的情况下,运行在Oracle Database、Sybase Adaptive Server和SQL Server上。

为了使本书中的代码尽量保持数据库平台版本独立性,作者不得不克制对MySQL SQL语言一些有趣特性的介绍,因为这些特性在其他数据库实现上不能被完成。作为补充,附录B覆盖了其中一些特性,以帮助那些准备持续使用MySQL的读者。

接下来4章的主要目标是简介SQL数据语句,重点放在select语句的3个主要子句上。此外还提供了许多银行业务方面的实例(在下一章中介绍),本书中所有的示例都围绕它们展开。这是因为使用同一个已熟悉的数据库作为例子,将会更容易地掌握问题的核心,而不是每次都需要了解所使用的表。如果读者对总是使用同样的表集合感到厌倦,那么可以在示例数据库中自由增加新表,或者干脆建立自己的试验数据库。

在帮助读者牢固掌握了基础知识后,剩余的章节将会深入讨论更多的概念,它们大多是相互独立的。因此,读者可以根据自己的疑问,自由地向前或向后浏览某个章节。当你完整阅读本书并使用过所有的示例后,你就已经在通往SQL专家的路上迈出了坚实的第一步。

在本章之外,如果读者还需要了解更多关系数据库、计算机数据库系统的历史以及SQL语言方面的知识,可以参考下面列出的一些资源:


相关图书

SQL实践教程(第10版)
SQL实践教程(第10版)
SQL初学教程(第3版)
SQL初学教程(第3版)
SQL学习指南(第3版)
SQL学习指南(第3版)
SQL入门经典(第6版)
SQL入门经典(第6版)
SQL优化核心思想
SQL优化核心思想
SQL初学者指南(第2版)
SQL初学者指南(第2版)

相关文章

相关课程