结构化查询语言(Structured Query Language,SQL)
SQL 的组成部分
SQL 是一种用来定义和操纵数据库对象的语言。使用 SQL 定义数据库表、将数据插入表中、修改表中的数据和从表中检索数据。与所有语言一样,SQL 也定义了语法和一套语言元素。
大多数 SQL 语句包含一个或多个以下语言元素:
单字节的字符 可以是字母(A-Z、a-z、$、# 和 @,或某个扩展字符集的成员)、数字(0-9)或特殊字符(包括逗号、星号、加号、百分号、与符号等等)。
标记(token) 是包含一个或多个字符的序列。它不能包含空白字符,除非它是被限界的标识符(由双引号包围的一个或多个字符)或字符串常量。
SQL 标识符 是用来形成名称的标记。
值的数据类型 决定 DB2 如何解释这个值。DB2 支持许多内置的数据类型,还支持用户定义的类型(UDT)。
常量 指定一个值。它们分为字符、图形或十六进制字符串常量,以及整数、小数或浮点数字常量。
特殊寄存器 是数据库管理程序为一个应用程序进程定义的一个存储区域,用来存储可以在 SQL 语句中引用的信息。特殊寄存器的示例是 CURRENT DATE、CURRENT DBPARTITIONNUM 和 CURRENT SCHEMA。
例程 可以是函数、方法或过程。
函数 表示一个或多个输入数据值与一个或多个结果值之间的关系。数据库函数可以是内置的或用户定义的。
列(即聚合)函数 对一个列中的一组值进行操作,返回单一值。例如:
SUM(sales) 返回 Sales 列中值的总和。
AVG(sales) 返回 Sales 列中值的平均值(即总和除以值的数量)
MIN(sales) 返回 Sales 列中的最小值。
MAX(sales) 返回 Sales 列中的最大值。
COUNT(sales) 返回 Sales 列中非空值的数量。
标量函数 对单一值进行操作,返回另一个单一值。例如:
ABS(-5) 返回 -5 的绝对值,即 5。
HEX(69) 返回数字 69 的十六进制表示,即 45000000。
LENGTH('Pierre') 返回字符串 “Pierre” 中的字节数量,即 6。对于 GRAPHIC 字符串,LENGTH 函数返回双字节字符的数量。
YEAR('03/14/2002') 提取 03/14/2002 的年份部分,即 2002。
MONTH('03/14/2002') 提取 03/14/2002 的月份部分,即 3。
DAY('03/14/2002') 提取 03/14/2002 的日部分,即 14。
LCASE('SHAMAN') 或 LOWER('SHAMAN') 返回已经转换为全小写字符的字符串,即 ‘shaman’。
UCASE('shaman') 或 UPPER('shaman') 返回已经转换为全大写字符的字符串,即 ‘SHAMAN’。
用户定义的函数使用 CREATE FUNCTION 语句注册到数据库的系统编目中(可以通过 SYSCAT.ROUTINES 编目视图访问)。
方法 也是一组输入数据值和一组结果值之间的关系。但是,数据库方法是作为用户定义的结构化类型的一部分隐式或显式地定义的。例如,一个称为 CITY 的方法(类型为 ADDRESS)接受 VARCHAR 类型的输入值,结果是 ADDRESS 的一个子类型。用户定义的方法使用 CREATE METHOD 语句注册到数据库的系统编目中(可以通过 SYSCAT.ROUTINES 编目视图访问)。关于结构化类型的更多信息,请参考 DB2 基础: 结构化数据类型和类型化表简介 。
过程 是一个可以通过执行 CALL 语句来启动的应用程序。过程的参数是不同类型的标量值,可以用来将值传递进过程中、接受过程的返回值或者同时有这两种作用。用户定义的过程使用 CREATE PROCEDURE 语句注册到数据库的系统编目中(可以通过 SYSCAT.ROUTINES 编目视图访问)。
表达式 指定一个值。有字符串表达式、算术表达式和情况表达式,情况表达式可以用来根据对一个或多个条件的计算来指定某一结果。
谓词(predicate) 指定关于给定的行或组的一个条件,结果可以是真、假或未知。谓词有几个子类型:
基本谓词 对两个值进行比较(例如,x > y)。
BETWEEN 谓词将一个值与一个值范围进行比较。
EXISTS 谓词测试某些行是否存在。
IN 谓词判断一个或多个值是否在一个值集合中。
LIKE 谓词搜索具有某一模式的字符串。
NULL 谓词测试空值。
数据操纵语言(Data Manipulation Language,DML)
使用 SELECT 语句从数据库表检索数据
SELECT 语句用来检索表或查看数据。最简单形式的 SELECT 语句可以用来检索一个表中的所有数据。例如,要从 SAMPLE 数据库中检索所有 STAFF 数据,应该发出以下命令:
SELECT * FROM staff
下面是这个查询返回的部分结果集:
ID | NAME | DEPT | JOB | YEARS | SALARY | COMM |
10 | Sanders | 20 | Mgr | 7 | 18357.50 | - |
20 | Pernal | 20 | Sales | 8 | 18171.25 | 612.45 |
30 | Marenghi | 38 | Mgr | 5 | 17506.75 | - |
要限制结果集中行的数量,可以使用 FETCH FIRST 子句,例如:
SELECT * FROM staff FETCH FIRST 10 ROWS ONLY
可以通过指定选择列表 从表中检索特定的列,选择列表由逗号分隔的列名组成。例如:
SELECT name, salary FROM staff
使用 DISTINCT 子句消除结果集中的重复行。例如:
SELECT DISTINCT dept, job FROM staff
使用 AS 子句给选择列表中的表达式或项目分配一个有意义的名称。例如:
SELECT name, salary + comm AS pay FROM staff
如果没有 AS 子句,派生的列会命名为 2,这表示它是结果集中的第二列。
使用 WHERE 子句和谓词限制查询返回的数据量
使用 WHERE 子句指定一个或多个搜索标准(即搜索条件),从而从表或视图选择特定的行。搜索条件 由一个或多个谓词组成。谓词指定关于行的某一情况(参见 SQL 的组成部分)。在构建搜索条件时,要确保:
算术操作只应用于数字数据类型
只在可比较的数据类型之间进行比较
将字符值包围在单引号中
字符值应该指定为与数据库中的值完全一样
我们来看几个示例。
寻找工资超过 $20,000 的职员的姓名:"SELECT name, salary FROM staff
WHERE salary > 20000"
将语句包围在双引号中,可以防止操作系统错误地解释特殊字符,比如 * 或 >;如果不这么做,大于号会被解释为输出重定向请求。
列出工资超过 $20,000 的不是经理的职员的姓名、头衔和工资:"SELECT name, job, salary FROM staff
WHERE job <> 'Mgr'
AND salary > 20000"
寻找以字母 S 开头的所有姓名:SELECT name FROM staff
WHERE name LIKE 'S%'
在这个示例中,百分号(%)是一个通配符,代表零个或多个字符的字符串。
子查询(subquery) 是主查询的 WHERE 子句中出现的 SELECT 语句,它将结果集提供给 WHERE 子句。例如:
"SELECT lastname FROM employee
WHERE lastname IN
(SELECT sales_person FROM sales
WHERE sales_date < '01/01/1996')"
相关名称(correlation name) 是在查询的 FROM 子句中定义的,可以作为表的简短名称。相关名称还可以消除对来自不同表的相同列名的二义性引用。例如:
"SELECT e.salary FROM employee e
WHERE e.salary <
(SELECT AVG(s.salary) FROM staff s)"
使用 ORDER BY 子句对结果进行排序
使用 ORDER BY 子句按照一个或多个列中的值对结果集进行排序。ORDER BY 子句中指定的列名不一定在选择列表中指定。例如:
"SELECT name, salary FROM staff
WHERE salary > 20000
ORDER BY salary"
在 ORDER BY 子句中指定 DESC 可以对结果集进行降序排序:
ORDER BY salary DESC
使用联结从多个表中检索数据
联结(join) 是一种将来自两个或更多表中的数据组合起来的查询。常常需要从两个或更多的表中选择信息,因为所需的数据常常是分散的。联结将列添加到结果集中。例如,对两个具有三列的表进行完全联结,会产生具有六列的结果集。
最简单的联结中没有指定条件。例如:
SELECT deptnumb, deptname, manager, id, name, dept, job
FROM org, staff
这个语句从 ORG 表和 STAFF 表返回列的所有组合。前三列来自 ORG 表,后四列来自 STAFF 表。这样的结果集(两个表的叉积(cross product))没什么用处。需要用一个联结条件(join condition) 来调整结果集。例如,下面这个查询标识出那些是经理的职员:
SELECT deptnumb, deptname, id AS manager_id, name AS manager
FROM org, staff
WHERE manager = id
ORDER BY deptnumb
下面是这个查询返回的部分结果集:
DEPTNUMB | DEPTNAME | MANAGER_ID | MANAGER |
10 | Head Office | 160 | Molinare |
15 | New England | 50 | Hanes |
20 | Mid Atlantic | 10 | Sanders |