2.3 数据查询

  在数据库操作中,查询是最常用的操作,也是最复杂的操作。根据不同的需求可以写出不同的SQL语句,甚至同一个需求也可以写出多个SQL语句。就像数学中的一题多解一样,其中肯定有一种高效率的写法。所以写好一个查询的SQL语句是非常重要的,它甚至可以影响程序的执行效率,进而决定程序的好坏。

  为了从数据库中查询数据,需要使用SQL中的SELECT语句。有时候并不需要获取表中所有的数据,也可以使用SQL语言中的一些关键字来对行或列进行限制。本节将介绍如何使用SELECT语句获取指定表中的数据。

  使用SELECT语句,可以进行列选择,即选择表中的列,这些列就是要获取的指定列;使用SELECT语句还可以进行行选择,即根据条件选择表中的行,并返回这些指定的行。使用SELECT语句还可以进行多表连接,这些数据原本存储在不同的表中,通过SELECT语句在它们之间建立起连接,形成一个满足特定连接需求的数据集合,关于多表连接的内容将会在后面的课程中介绍。SELECT语句的功能如图2.13所示。

2.3 数据查询 - 图1


图2.13 SELECT语句功能

2.3.1 基本SELECT语句

  SELECT语句的基本语法形式如下:

  1. SELECT *|字段名|表达式 FROM 表名 [WHERE 条件 [ORDER BY 字段名]]

  在最简单的形式中,SELECT语句必须包含一个SELECT子句,指定需要显示的字段;还需要一个FROM子句,指定从哪个表获取数据。

  语法解释如下。

  • *:选择表中的所有字段。

  • 字段名:选择表中的字段名称,可以选择多个字段,各个字段间用逗号分隔。

  • 表达式:由字段、函数等组成。

  • 表名:指定包含字段的表。

  • WHERE条件:查询的条件,可以通过该条件进行行选择。

  • ORDER BY字段名:要求在查询的结果中进行排序,默认是升序ASC,若希望是降序则使用关键字DESC。

  假设要通过SQL语句查询DEPARTMENTS表中所有列、所有行的数据,可以使用下面的语句:

  1. SELECT * FROM DEPARTMENTS

  要想让上面的SQL语句在PL/SQL Dev中执行,可以通过单击PL/SQL Dev左上角第一个图标img新建一个SQL Window,如图2.14所示。在打开的SQL Window中输入SQL语句(这里SQL语句使用小写,SQL是不区分大小写的),并以“;”结尾,单击左上角第二排第二个图标img(或按F8键)执行该SQL语句,返回需要查询的结果集,如图2.15所示。由于窗口显示内容的限制,可能仅显示了部分数据,通过单击imgimg图标,可以显示下一页和到最后页的数据。

2.3 数据查询 - 图6


图2.14 新建一个SQL Window

2.3 数据查询 - 图7


图2.15 执行SELECT语句

  通过查询结果和之前对DEPARTMENTS表的了解,知道此表包括DEPARTMENT_ID、DEPARTMENT_NAME、MANAGER_ID和LOCATION_ID四个字段,如果仅想查询部门编号和部门名称这两个字段,可以编写如下的SQL语句(为了方便阅读,接下来编写的SQL语句中,SQL关键字将采用大写字母,非SQL关键字将采用小写字母,这也符合日常程序员编写SQL语句的习惯)。

  1. SELECT department_id,department_name FROM departments

  在SELECT子句中,所选择字段的显示顺序可以由程序员自己决定,例如想把部门名称字段显示在部门编号之前,则可以编写如下SQL语句:

  1. SELECT department_name, department_id FROM departments

  从现在开始,需要大量编写SQL语句了,在编写SQL语句之前,先了解一下作为软件开发人员,编写SQL语句应该遵循哪些规则。遵循了这些规则编写的SQL语句,容易阅读、容易编辑,但因为书籍篇幅问题,书中的SQL语句大多没有采用如下规则。

  • SQL语句对大小写不敏感,但通常SQL关键字采用大写字母,非SQL关键字采用小写字母。

  • SQL语句可以写成一行或多行,为了易于阅读和编辑,子句通常放在不同的行,且使用缩进。

  例如上面的SQL语句,按SQL语句需遵循的规则,应该写成:

  1. SELECT department_name, department_id
  2. FROM departments

2.3.2 算术表达式

  数据库表中存储的数据,可能并不是最终要显示的数据,会存在需要修改数据显示内容以达到显示所需数据的目的,这样就可能会用到算术表达式。一个算术表达式可以包含字段名、固定的数字值和算术运算符。

  Oracle中的算术运算符,没有Java中的算术运算符丰富,只有“+”、“-”、“*”、“/”四个,其中“/”运算的结果是浮点数。求余运算只能借助函数MOD(x,y)来完成,这个函数的作用就是返回x除以y的余数。

  要特别说明一点,在Oracle中,可以对DATE和TIMESTAMP类型进行加、减操作,具体加、减的含义和用法,在后面的课程中会讲到。

  现在有这样的需求:过圣诞节了,公司决定给每个雇员发500元过节费,随薪水一起发放。现需要显示出每个员工的编号、名字和当月实发薪酬,可以编写如下SQL语句:

  1. SELECT employee_id,first_name,salary+500 FROM employees

  SQL语句中合成的计算列不是employees表中新的字段,显示的新列来源于对字段的计算而已。

  如果需要显示每个雇员的月薪以及年薪,可以通过月薪*12+500元过节费的方式计算年薪并显示,其SQL语句如下:

  1. SELECT employee_id,first_name,salary, salary*12+500 FROM employees

  部分显示结果如图2.16所示。

2.3 数据查询 - 图8


图2.16 SQL算数表达式

2.3.3 字段别名

  在显示月薪、年薪的例子中,年薪字段的标题为“SALARY*12+500”,这样的描述难以理解,不能满足用户的需求,接下来通过字段别名的方法解决这个问题。

  在SELECT所选字段后面可以指定别名,字段名和别名之间用空格分开。在默认情况下,别名标题用大写字母显示,如果别名中包含空格或者特殊字符(如#或&),或者大小写敏感,需要将别名放在双引号中。

  还是上面显示雇员编号、名字、月薪和年薪的例子,这次要求做两点改进,一是只需要显示雇员名字和年薪两个字段的数据,二是雇员名字字段显示的标题为Name而不是FIRST_NAME,年薪字段的标题改为Yearly Salary,其SQL语句如下:

  1. SELECT first_name "Name",salary*12+500 "Yearly Salary" FROM employees

  因为字段别名要求大小写敏感,而且带有空格,所以使用了双引号,部分显示结果如图2.17所示。

2.3 数据查询 - 图9


图2.17 SQL字段别名

  也可以使用可选关键字AS表示别名,SQL语句如下,功能与之前的SQL语句没有差别,但为了阅读方便,推荐软件开发人员使用该关键字。

  1. SELECT first_name AS "Name",salary*12+500 AS "Yearly Salary" FROM employees

2.3.4 连字运算符

  在实际编程过程中,因为业务需求,可能需要将两个或多个字段连接成一个字段显示,这就要用到连字运算符“||”。使用连字运算符,可以进行字段与字段、字段与表达式、字段与常数值之间的连接,来创建一个字符表达式,连字运算符两边的字段被合并成一个单个的列输出。

  继续调整上面的案例,如果想将first_name和last_name合并成一个字段显示,且字段标题设置为Name,其SQL语句如下:

  1. SELECT first_name || last_name AS "Name",salary*12+500 AS "Yearly Salary" FROM employees

  部分显示结果如图2.18所示。

  从显示结果可以看到,连字运算符“||”连接了first_name和last_name两个字段。但是在将这两个字段连接时,中间没有空格,并不是理想的结果。针对这样的情况,可以使用连字运算符“||”将字段和字符串常量(包括数字、日期类型)进行连接以达到目的,具体SQL语句如下,执行结果如图2.19所示。

2.3 数据查询 - 图10


图2.18 SQL连字运算符之非理想结果

2.3 数据查询 - 图11


图2.19 SQL连字运算符之理想结果

  1. SELECT first_name || ' ' || last_name AS "Name",salary*12+500 AS "Yearly Salary" FROM employees

  需要注意的是,如果连接的是数字,则可以不用单引号;如果是字符串或日期类型,则必须使用单引号;如果字符串常量中包含了单引号,则可以使用两个单引号表示一个单引号常量。

2.3.5 去除重复行

  如果需要查询显示employees表中员工的部门编号,其SQL语句非常简单:

  1. SELECT department_id FROM employees

  部分显示结果如图2.20所示。可以看出,部门编号存在大量的重复,这说明SELECT语句默认显示所有的行,包括相同的行,如果想除去相同的行,需要使用DISTINCT关键字,具体SQL语句如下:

  1. SELECT DISTINCT department_id FROM employees

  结果如图2.21所示。

2.3 数据查询 - 图12


图2.20 SELECT存在重复的行

2.3 数据查询 - 图13


图2.21 SQL DISTINCT关键字

  为了在结果中除去相同的行,在SELECT子句中的SELECT关键字后面紧跟DISTINCT关键字。在DISTINCT关键字后面,可以指定多个字段,DISTINCT关键字影响所有被选定的字段组合的结果。