SQL 是计算机世界的语言,在用关系数据库开发报表时,将数据放入数据库以及从数据库中取出来,都需要SQL 的知识。很多人以一种马马虎虎的态度在使用SQL,根本没有意识到自己掌握着多么强大的武器。本书的目的是打开读者的视野,看看SQL 究竟能干什么,以改变这种状况。\r\n 本书是一本指南,其中包含了一系列SQL 的常用问题以及它们的解决方案,希望能对读者的日常工作有所帮助。本书将相关主题的小节归成章,如果读者遇到不能解决的SQL 新问题,可以先找到最可能适用的章,浏览其中各小节的标题,希望读者能从中找到解决方案,至少可以找到点灵感。\r\n 在这本书中有150 多个小节,这还仅仅是SQL 所能做的事情的一鳞半爪。解决日常编程问题的解决方案的数量仅取决于需要解决的问题的数量,本书没有覆盖所有问题,事实上也不可能覆盖;然而从中可以找到许多共同的问题及其解决方案,这些解决方案中用到许多技巧,读者学到这些技巧就可以将它们扩展并应用到本书不可能覆盖的其他新问题上。\r\n 毫无疑问,本书的目标是让读者看到,SQL 能够做多少一般认为是SQL 问题范围之外的事情。在过去的10 年间,SQL 走过了很长的路,许多过去只能用C 和JAVA等过程化语言解决的典型问题现在都可以直接用SQL 解决了,但是很多开发人员并没有意识到这一事实。本书就是要帮助大家认识到这一点。\r\n 现在,在对我刚才的话产生误解之前我先要申明:我是“如果没坏,就别去修它”这一教义的忠实信徒。例如,假如你有一个特定的业务问题要解决,目前只用SQL检索数据,而其他复杂的业务逻辑由其他语言完成,如果代码没有问题,而且性能也过得去,那么,谢天谢地。我绝对无意建议你扔掉以前的代码重新寻求完全SQL 的解决方案;我只是请你敞开思想,认识到1995 年编程用的SQL 跟2005 年用的不是一回事,今天的SQL 能做的事要多得多。
第1章 检索记录 \r\n 1.1 从表中检索所有行和列 \r\n 1.2 从表中检索部分行 \r\n 1.3 查找满足多个条件的行 \r\n 1.4 从表中检索部分列 \r\n 1.5 为列取有意义的名称 \r\n 1.6 在WHERE子句中引用取别名的列 \r\n 1.7 连接列值 \r\n 1.8 在SELECT语句中使用条件逻辑 \r\n 1.9 限制返回的行数 \r\n 1.10 从表中随机返回n条记录\r\n 1.11 查找空值 \r\n 1.12 将空值转换为实际值 \r\n 1.13 按模式搜索 \r\n第2章 查询结果排序 \r\n 2.1 以指定的次序返回查询结果 \r\n 2.2 按多个字段排序 \r\n 2.3 按子串排序 \r\n 2.4 对字母数字混合的数据排序 \r\n 2.5 处理排序空值 \r\n 2.6 根据数据项的键排序 \r\n第3章 操作多个表 \r\n 3.1 记录集的叠加 \r\n 3.2 组合相关的行 \r\n 3.3 在两个表中查找共同行 \r\n 3.4 从一个表中查找另一个表没有的值 \r\n 3.5 在一个表中查找与其他表不匹配的记录 \r\n 3.6 向查询中增加联接而不影响其他联接 \r\n 3.7 检测两个表中是否有相同的数据 \r\n 3.8 识别和消除笛卡儿积 \r\n 3.9 聚集与联接 \r\n 3.10 聚集与外联接 \r\n 3.11 从多个表中返回丢失的数据 \r\n 3.12 在运算和比较时使用NULL值 \r\n第4章 插入、更新与删除 \r\n 4.1 插入新记录 \r\n 4.2 插入默认值 \r\n 4.3 使用NULL代替默认值 \r\n 4.4 从一个表向另外的表中复制行 \r\n 4.5 复制表定义\r\n 4.6 一次向多个表中插入记录 \r\n 4.7 阻止对某几列插入 \r\n 4.8 在表中编辑记录 \r\n 4.9 当相应行存在时更新 \r\n 4.10 用其他表中的值更新 \r\n 4.11 合并记录 \r\n 4.12 从表中删除所有记录 \r\n 4.13 删除指定记录 \r\n 4.14 删除单个记录 \r\n 4.15 删除违反参照完整性的记录 \r\n 4.16 删除重复记录 \r\n 4.17 删除从其他表引用的记录 \r\n第5章 元数据查询 \r\n第6章 使用字符串 \r\n第7章 使用数字 \r\n第8章 日期运算 \r\n第9章 日期操作 \r\n第10章 范围处理 \r\n第11章 高级查找 \r\n第12章 报表和数据仓库运算\r\n第13章 分层查询 \r\n第14章 若干另类目标 \r\n附录A 窗口函数补充 \r\n附录B 回顾Rozenshtein
Anthony Molinaro是wireless Generation公司的数据库开发人员。他多年从事帮助开发人员改进其sQL查询的工作,具有丰富的实践经验。Anthony酷爱sQL,在相关领域,他小有名气,客户在遇到困难的sQL查询问题时,就会想到他,他总能起到关键作用。他博学多才,对关系理论有深入的理解,有9年解决复杂sQL问题的实战经验。Anthony通晓新的和功能强大的sQL功能,比如,添加到最新sQL标准中的窗口函数语法等。
SQL 是计算机世界的语言,在用关系数据库开发报表时,将数据放入数据库以及从数据
库中取出来,都需要SQL 的知识。很多人以一种马马虎虎的态度在使用SQL,根本没有
意识到自己掌握着多么强大的武器。本书的目的是打开读者的视野,看看SQL 究竟能干
什么,以改变这种状况。
本书是一本指南,其中包含了一系列SQL 的常用问题以及它们的解决方案,希望能对读
者的日常工作有所帮助。本书将相关主题的小节归成章,如果读者遇到不能解决的SQL
新问题,可以先找到最可能适用的章,浏览其中各小节的标题,希望读者能从中找到解
决方案,至少可以找到点灵感。
在这本书中有150 多个小节,这还仅仅是SQL 所能做的事情的一鳞半爪。解决日常编程
问题的解决方案的数量仅取决于需要解决的问题的数量,本书没有覆盖所有问题,事实
上也不可能覆盖;然而从中可以找到许多共同的问题及其解决方案,这些解决方案中用
到许多技巧,读者学到这些技巧就可以将它们扩展并应用到本书不可能覆盖的其他新问
题上。
注意:我和出版商一直在搜集适合指南的新SQL 方案,如果您有对某问题的好的(或聪明的)解
决方案,能否与大家共享?能否发给我们,以便用于本书的下一个版本。有关我们的联系
信息请参阅“注释与问题”。
为何要写本书
查询,查询,还是查询。项目开始时我并没有如此强烈的愿望要将“SQL 指南”写成一
本“查询指南”。我的目标是写这么一本书,其中包含从简单到复杂的查询,使读者能掌
握查询中使用的技巧,并用来解决他们自己的实际业务问题。我希望能将自己职业生涯
前言
中所积累的SQL 编程技巧传递给读者,使他们能够看到、能够从中学到,并最终可以加
以改进;通过这么一个循环,我们双方都会获益。从数据库中检索数据看似一件容易的
事,然而,在IT 世界里,尽可能高效地检索数据至关紧要,高效检索数据的技巧应该与
大家分享,这样大家都会很高效,并互相帮助、共同提高。
想一想数学家Georg Cartor的杰出贡献,是他首先认识到研究元素集合(研究集合本身,
而不是其中的元素)的巨大利益。起初,Cantor 的工作并没有得到他许多同伴的认同,尽
管如此,随着时间的推移,不仅他的工作得到了认同,而且现在人们已经把集合论视为
数学的基础。然而更重要的是,集合论取得今天的成就并非Cantor 一个人的功劳,通过
分享他的思想,其他人,如Ernst Zermelo、Gottlob Frege、Abraham Fraenkel、Thoralf
Skolem、 Kurt G_del 以及John von Neumann 等人,对集合理论作了进一步的发展和提
高。这样的分享不仅使每个人可以更好地理解集合论,而且使结合论本身比最初的构想
更趋完善。
本书的目标
毫无疑问,本书的目标是让读者看到,SQL 能够做多少一般认为是SQL 问题范围之外的
事情。在过去的10 年间,SQL 走过了很长的路,许多过去只能用C 和JAVA等过程化语
言解决的典型问题现在都可以直接用SQL 解决了,但是很多开发人员并没有意识到这一
事实。本书就是要帮助大家认识到这一点。
现在,在对我刚才的话产生误解之前我先要申明:我是“如果没坏,就别去修它”这一
教义的忠实信徒。例如,假如你有一个特定的业务问题要解决,目前只用SQL检索数据,
而其他复杂的业务逻辑由其他语言完成,如果代码没有问题,而且性能也过得去,那么,
谢天谢地。我绝对无意建议你扔掉以前的代码重新寻求完全SQL 的解决方案;我只是请
你敞开思想,认识到1995 年编程用的SQL 跟2005 年用的不是一回事,今天的SQL 能做
的事要多得多。
本书的读者
本书在这一点上很独特:其目标读者非常广泛,而其内容却没有做折衷。想一想,其中
既有简单方案,又有复杂方案;而且当一个问题没有统一方案时会提供5 个不同数据库
厂商的解决方案。本书的目标读者确实很广泛:
SQL 新手
你可能刚买了本SQL 的书开始学习,也可能是初修数据库课程的学生,你可能希望
通过一些富有挑战性的现实中的例子来拓展自己的知识面。你以前可能看到过用查
询魔术般地将行转换成列,或者将连续的字符串解析成结果集,本书中的各节将向
你介绍这些看似不可能的查询中所使用的技巧。
前言
非SQL 程序员
你的背景可能是其他语言,而目前的工作要求你去维护别人编写的复杂的SQL,你
觉得犹如置身火中。本书中的各节,尤其是后面几章,会将复杂的查询分解开,带
你一步步“潇洒走一回”,帮你理解可能会接手的复杂代码。
SQL 高手
对中级SQL开发人员而言,本书就是“彩虹那端的黄金”(对,可能说得太过了;请
原谅一个作者对自己理念的醉心)。特别是,如果你编写SQL 代码时间不短了,但
还没有用上窗口函数,那么本书对你就是一顿大餐。例如,需要用临时表存放中间
结果集的日子已经过去了,利用窗口函数可以用一个查询就解决问题!请允许我重
申一下:我无意向任何有经验的同仁灌输我的思想;如果你还没有理解SQL的新增
功能的话,请将本书作为更新技能的途径。
SQL 专家
毫无疑问,你以前已经看到过这样的方案了,而且自己可能有所改进,那么本书对
你还有什么用呢?在你的整个职业生涯中,你可能是某个平台的SQL 专家,比如,
SQL Server,现在想学Oracle;你可能只用过MySQL,并且想知道同一问题在
PostgreSQL 中的解决方案是怎么样的。本书覆盖了5 种不同的关系数据库系统
(RDBMS),并一步步展示这些解决方案。这是你拓展知识基础的好机会。
如何使用本书
务必请通读本前言,如果直接进入各小节,就会错失一些背景信息。“平台和版本”一节
交待了本书所覆盖的RDBMS;要特别注意一下“本书使用的表”一节,这样就会熟悉大
部分小节中的示例表;“本书的约定”一节中包含了一些重要的代码和字体约定。所有这
些小节都是本章的内容。
记住这是一本指南,是一系列代码示例,用于指导解决可能遇到的类似(或相同)的问
题。本书不是用来学习SQL 的,至少不是从头开始,它可以用作SQL 教程的补充,但不
能代替教程。此外,以下提示会有助于更有效地使用本书:
.
本书中使用了各厂商的专用函数,Jonathan Gennick 的SQL Pocket Guide 一书中
都有介绍,如果你对本书各小节中有些函数还不了解的话,有这么一本书在手头是
很方便的。
.
如果你从来没有使用过窗口函数,或者对使用GROUP BY 的查询有问题,请先看
附录A,其中会给出SQL 中组的定义并作证明;更重要的是,它介绍了窗口函数工
作方式的基本思路,窗口函数是过去十年中SQL 最重要的发展。
.
利用常识。要知道,不可能写一本包罗所有问题解决方案的书,然而,可以将本书
中的方案作为模板或指导思想,让自己学到其中的技巧,解决自己的问题。有人可
前言
能会说:“好是好,就是这些方案只能用于书上那个数据集,而我的数据集不一样,
所以不能用”。一点也不意外。如果是这样的话,先设法找出书上的数据跟你自己的
数据之间的共同点,将书中的查询分解成最简单的形式,然后逐步增加其复杂度。
所有的查询都包含SELECT ... FROM ...,这是它们最简单的形式,所有查询都一
样;在增加复杂度的过程中,可以每次增加一个函数,或每次增加一个联接,这样
不但有助于理解查询结构对结果集的影响,而且可以看出书中的方案跟自己的实际
需要之间差别何在。然后,就可以按照自己的数据集做相应的修改。
.
测试,测试,再测试。毫无疑问,实际使用的表比书中所举的14 行的EMP 表要大
得多,所以要用自己的数据集对解决方案做测试,锱铢必究地致力提高性能。我不
可能知道你的表是什么样的,不知道它们如何索引,也不知道模式中的关系,所以,
除非你完全理解了这些技巧以及它们在自己数据上的性能,请不要盲目在产品代码
中使用这些技巧。
.
要勇于试验,要有创新精神,你完全可以使用其他技巧。我在本书中用了各厂商特
定的函数,通常其他还有许多其他函数完成同样的功能。你可以随意对本书给出的
方案进行修改。
.
新并不一定意味着好。如果你目前没有使用SQL 语言的一些新特性(比如窗口函
数),这并不意味着你的代码一定不高效。很多情况下传统SQL 解决方案跟新方案
不相上下,有时甚至更好。请一定要记住这一点,尤其是在附录B“回顾Rozenshtein”
中。读完本书,你不应该觉得要将现有所有代码重写,而是要认识到,现在SQL 已
经有更多非常高效的特性,这些东西10 年前是没有的,很值得花点时间去学习。
.
不要被吓倒。如果一个解决方案看起来不可能理解,不要害怕。我竭尽全力,不仅
将查询分解,从最简单的形式开始,而且还给出了每一部分的中间结果。你可能不
能马上看清全局,但只要跟随着讨论的思路,就可以看到查询建立起来的过程集及
中间结果,而且会发现,即使是看起来非常费解的查询其实也不难掌握。
.
必要时采取防范措施。在不导致误解或歧义的前提下,为了尽可能保持书中查询的
简洁,我去掉了很多“防范措施”。例如,对计算员工工资累加和的查询,情况可能
会是这样的:工资列定义为VARC
无封面