3编写SELECT语句
SELECT语句是最重要且最复杂的SQL语句。可使用它和SQL语句INSERT、 UPDATE和DELETE操纵数据。可以使用SELECT语句从数据库检索数据。将它用作 INSERT语句的一部分来生成新行或将它作为UPDATE语句的一部分来更新信息。
SELECT语句是查询数据库中信息的主要方法。它是检索程序、报告、表单或电子表格中 的数据的关键。可以将SELECT语句与查询工具DB-Access配合使用或在应用程序中嵌入 SELECT 语句。
本章介绍了使用SELECT语句查询和检索关系数据库数据的基本方法。本章讨论如何调整 语句以从一个或多个表中选择信息行和列,如何在SELECT语句中包含表达式和函数以 及如何创建数据库表之间的各种连接条件。SELECT语句的语法和使用方法在GBase 8s SQL指南:语法中有详细描述。
本出版物中的大部分示例来自stores_demo数据库中的各表,该数据库随GBase 8s SQL API 或数据库实用程序的软件提供。为了简便起见,示例只显示了每个SELECT语句检索的数 据的一部分。有关演示数据库的结构和内容的信息,请参阅《GBase 8s SQL参考指南》。 为了着重强调,虽然SQL不区分大小写,但是在示例中用大写字母显示关键字。
3.1介绍SELECT语句
SELECT语句允许您查看关系数据库中的数据的子句构成。这些子句允许您从一个或多个 表或视图中选择列和行、指定一个或多个条件、对数据进行排序和总结以及将选择的数据 放置在临时表中。
本章介绍了如何使用五个SELECT语句子句。如果包含全部五个子句,那么它们必须按照 下列顺序岀现在SELECT语句中:
只有Projection子句和FROM子句是必需的。这两个子句构成每个数据库查询的基础, 原因是它们指定要检索的列值,以及包含这些列的表。使用以下列表中的一个或多个其它 子句:
•添加WHERE子句以选择特定行或创建连接条件。
还有两个SELECT语句子句GROUP BY和HAVING,使您可以执行更复杂的数据检索。 编写高级SELECT语句中对它们进行了描述。另一个子句INTO指定要从应用程序中的 SELECT语句中接收数据的程序或主变量。关于使用SELECT语句的完整语法和规则在 GBase 8s SQL指南:语法中有所描述。
- SELECT语句的输出
虽然在所有GBase 8s产品中语法相同,但是结果输出的格式和显示取决于应用程序。本章 和编写高级SELECT语句中的示例如同您在DB-Access中使用“交互式查询语言”选项 时那样显示SELECT语句及输出。
当发出包含大对象的SELECT语句时,DB-Access按如下所示显示结果:
DB-Access使用特殊约定来显示包含复杂或不透明数据类型的列的输出。
可以发出查询NCHAR列而不是CHAR列,或者NVARCHAR列而不是VARCHAR列 的SELECT语句。
SELECT语句不同于INSERT、UPDATE和DELETE语句,它不修改数据库中的数据。 一次只能有一个用户修改数据,而多个用户可同时查询或选择数据。有关修改数据的语句 的更多信息,请参阅修改数据。INSERT、UPDATE和DELETE语句的语法描述位于
《GBase 8s SQL指南:语法》中。
在关系数据库中,列是包含岀现在表中的每一行中的特定信息类型的数据元素。行是在数 据库表中的所有列上有关单个实体的信息的一组相关项。
可以从数据库表、系统目录表(包含有关数据库的信息的特殊表)、或视图(创建来包含 一组定制数据的虚拟表)中选择列和行。有关系统目录表的信息在GBase 8s SQL参考指 南中有所描述。
在查询数据之前,确保您对数据库具有Connect特权和表的Select特权。通常这些特权授 予所有用户。在GBase 8s SQL指南:语法的GRANT和REVOKE语句中描述了数据库 访问权。
关系操作涉及处理一个或多个表或者关系以产生另一个表,三种关系操作为选择、投影和 连接。本章包括选择、投影和连接操作的一些示例。
在关系术语中,选择被定义为取得满足特定条件的单个表的行的水平子集。此类SELECT 语句返回表中的某些行和所有列。选择是通过SELECT语句的WHERE子句实现的,如 下图所示:
图:查询
SELECT * FROM customer WHERE state = 'NJ';
该结果包含的列数与customer表相同,但只是后者的行的子集。在此示例中,DB-Access显 示单独行上来自每列的数据。
图:查询结果
customejnum 119 |
|
fname |
Bob |
lname |
Shorter |
company |
The Triathletes Club |
address1 |
2405 Kings Highway |
address2 |
|
city |
Cherry Hill |
state |
NJ |
zipcode |
08002 |
phone |
609-663-6079 |
customejnum 122 |
|
fname |
Cathy |
lname |
O'Brian |
company |
The Sporting Life |
address1 |
543d Nassau |
address2 |
|
city |
Princeton |
state |
NJ |
zipcode |
08540 |
phone |
609-342-0054 |
在关系术语中,投影被定义为从保留唯一行的单个表的列中获取垂直子集。此类S ELECT语 句返回表中的某些行和某些列。
投影是通过SELECT语句的Projection子句中的投影列表实现的。如下图所示。
图:查询
SELECT city, state, zipcode FROM customer;
此结果包含的列数与customer表相同,但只是投影表中列的子集。因为只从每行中选择一 小部分的数据,所以DB-Access能够在一行上显示行的所有数据。
图:查询结果
city state zipcode
Sunnyvale |
CA |
94086 |
San Francisco |
CA |
94117 |
Palo Alto |
CA |
94303 |
Redwood City |
CA |
94026 |
Los Altos |
CA |
94022 |
Mountain View |
CA |
94063 |
Palo Alto |
CA |
94304 |
Redwood City |
CA |
94063 |
Sunnyvale |
CA |
94086 |
Redwood City |
CA |
94062 |
Sunnyvale |
CA |
94085 |
Oakland |
CA |
94609 |
Cherry Hill |
NJ |
08002 |
Phoenix |
AZ |
85016 |
Wilmington |
DE |
19898 |
Princeton |
NJ |
08540 |
Jacksonville |
FL |
32256 |
Bartlesville |
OK |
74006 |
最常见的SELECT语句都同时使用选择和投影。此类查询返回表的某些行和某些列。如下 图所示。
图查询
SELECT UNIQUE city, state, zipcode
FROM customer
WHERE state = 'NJ';
图6包含customer表的列的子集和行的子集。
图:查询结果
city state zipcode
Cherry Hill NJ 08002
Princeton NJ 08540
当两个或多个表被同一列或多个列连接时发生连接,它创建新的结果表。下图显示了一个 查询,该查询使用items和stock表的子集来说明连接的概念。
图:两个表之间的连接
SELECT UNOJE ltem_num. orO9r_num.
stock.stock_nMTi. desciip^iion
FROM items, slock
WHERE fiems.stock num = skx^k.stoclc num
正在上传…重新上传取消 |
下列查询将customer和state表连接起来。
图:查询
SELECT UNIQUE city, state, zipcode, sname
FROM customer, state
WHERE customer.state = state.code; 该结果包含customer和state表的指定行和列。
图:查询结果
city state zipcode sname
Bartlesville |
OK |
74006 |
Oklahoma |
Blue Island |
NY |
60406 |
New York |
Brighton |
MA |
02135 |
Massachusetts |
Cherry Hill |
NJ |
08002 |
New Jersey |
Denver |
CO |
80219 |
Colorado |
Jacksonville |
FL |
32256 |
Florida |
Los Altos |
CA |
94022 |
California |
Menlo Park |
CA |
94025 |
California |
Mountain View |
CA |
94040 |
California |
Mountain View |
CA |
94063 |
California |
Oakland |
CA |
94609 |
California |
Palo Alto |
CA |
94303 |
California |
Palo Alto |
CA |
94304 |
California |
Phoenix |
AZ |
85008 |
Arizona |
Phoenix |
AZ |
85016 |
Arizona |
Princeton |
NJ |
08540 |
New Jersey |
Redwood City |
CA |
94026 |
California |
Redwood City |
CA |
94062 |
California |
Redwood City |
CA |
94063 |
California |
San Francisco |
CA |
94117 |
California |
Sunnyvale |
CA |
94085 |
California |
Sunnyvale |
CA |
94086 |
California |
Wilmington |
DE |
19898 |
Delaware |
3.2单个表的SELECT语句
可用多种方法查询数据库中的单个表。可用调整SELECT语句以执行以下操作:
,检索所有或指定的列
•检索所有或指定的行
,对检索到的数据执行计算或其它功能
,用各种方法对数据进行排序
最基本的SELECT语句只包含两个必需的子句,即Projection子句和FROM。
3.2.1使用星号(*)
下列查询在投影列表中指定manufact表中所有的列。显式投影列表是想要从表投影的列名 或表达式的列表。
图:查询
SELECT manu_code, manu_name, lead_time FROM manufact;
以下查询使用通配符星号(*)作为选择列表中的简写来表示表中所有名称相同的列。当想 要所有列按其定义的顺序排列时,可使用星号(*),隐式选择列表使用星号。
图:查询
SELECT * FROM manufact;
因为manufact表只含有三列,图1和图2是等价的,并且显示相同的结果。即,manufact表 中每个列和行的列表。下图显示了结果。
图:查询结果
manu_code manu_name lead_time
SMT |
Smith |
3 |
ANZ |
Anza |
5 |
NRG |
Norge |
7 |
HSK |
Husky |
5 |
HRO |
Hero |
4 |
SHM |
Shimara |
30 |
KAR |
Karsten |
21 |
NKL |
Nikolus |
8 |
PRC |
ProCycle |
9 |
下列查询显示了如何通过更改列在投影列表中的顺序。
图:查询
SELECT manu_name, manu_code, lead_time FROM manufact; 该查询结果包含与前一查询结果相同的列,但因为用不同的顺序指定了列,所以显示也不 同。
图:查询结果
manu_name manu_code lead_time
Smith |
SMT |
3 |
Anza |
ANZ |
5 |
Norge |
NRG |
7 |
Husky |
HSK |
5 |
Hero |
HRO |
4 |
Shimara |
SHM |
30 |
Karsten |
KAR |
21 |
Nikolus |
NKL |
8 |
ProCycle |
PRC |
9 |
3.2.2使用ORDER BY子句存储行
不以任何特定顺序排列查询的结果。例如:图4和图2以随机顺序显示。
可以将ORDER BY子句添加到您的SELECT语句里指导系统以特定顺序对数据进行排 序。ORDER BY子句是任何远程或本地表或视图中的列名的列表。投影列表中允许的所有 表达式在ORDER BY列表中也允许。如果在ORDER BY列表中使用的列具有选择触发 器,那么将不会激活该触发器。
以下查询返回manufact表中manu_code、manu_name和lead_time列的每一行。并根 据lead_time进行排序。
图:查询
SELECT manu_code, manu_name, lead_time
FROM manufact
ORDER BY lead_time;
对于GBase 8s,不需要在投影列表中包括您想要在ORDER BY子句中使用的列。即,可 以根据不在投影列表中检索的列对数据进行排序。以下查询返回manufact表
中 manu_code、manu_name列的每一行,并根据lead_time进行排序。lead_time列位于 ORDER BY子句中(尽管未包含在投影列表中)。
图:查询
SELECT manu_code, manu_name
FROM manufact
ORDER BY lead_time;
缺省情况下,检索到的数据按升序顺序排序。在ASCII字符集中,升序是从大写字母A到 小写字母z,对于字符数据类型,那么是从最小值到最大值。DATE和DATETIME数据 按照从最早到最新排序,INTERVAL数据按从时间范围最短到最长排序。
降序与升序相反,对于字符类型为从小写z到大写A,对于数字类型为从最大值到最小值。 DATE和DATETIME数据按照从最新到最早排序,INTERVAL数据按从时间范围最长到 最短排序。以下查询显示了降序的示例。
图:查询
SELECT * FROM manufact ORDER BY lead_time DESC;
列名后跟关键字DESC导致以降序对检索数据进行排序,如下图所示:
图:查询结果
manu_code manu_name lead_time
SHM |
Shimara |
30 |
KAR |
Karsten |
21 |
PRC |
ProCycle |
9 |
NKL |
Nikolus |
8 |
NRG |
Norge |
7 |
HSK |
Husky |
5 |
ANZ |
Anza |
5 |
HRO |
Hero |
4 |
SMT |
Smith |
3 |
您可以在ORDER BY子句中指定任何内置数据类型的列(TEXT、BYTE、BLOB或 CLOB除外),数据库服务器根据该列中的值对数据进行排序。
还可以使用ORDER BY排序两个或多个列,这会创建嵌套排序。缺省值仍然是升序。在 ORDER BY子句中最先列出的列优先。
下列查询和图2及相应的查询结果显示了嵌套排序。要修改显示所选数据的顺序。更改在 ORDER BY子句中命名的两个列的顺序。
SELECT stock_num, manu_code, description, unit_price
FROM stock
ORDER BY manu_code, unit_price;
查询结果中,manu_code列数据按字母顺序显示,并且在同一 manu_code (例如:ANZ、 HRO)中,unit_price以升序列出。
图:查询结果
stock_num manu_code description unit_price
5 ANZ |
tennis racquet |
$19.80 |
9 ANZ |
volleyball net |
$20.00 |
6 ANZ |
tennis ball |
$48.00 |
313 ANZ |
swim cap |
$60.00 |
201 ANZ |
golf shoes |
$75.00 |
310 ANZ |
kick board |
$84.00 |
111 SHM |
10-spd, assmbld |
$499.99 |
112 SHM |
12-spd, assmbld |
$549.00 |
113 SHM |
18-spd, assmbld |
$685.90 |
5 SMT |
tennis racquet |
$25.00 |
6 SMT |
tennis ball |
$36.00 |
1 SMT |
baseball gloves |
$450.00 |
下列查询显示了 ORDER BY子句中列的相反顺序。
图查询
SELECT stock_num, manu_code, description, unit_price
FROM stock
ORDER BY unit_price, manu_code;
在此查询结果中,数据按unit_price的升序显示,其中两个或多个行具有相同的unit_price (例如:$20.00、$48.00、$312.00), manu_code 以字母顺序显示。
图: 查询结果
stock_num manu_code description unit_price |
|||||
302 HRO |
ice pack |
$4.50 |
|||
302 KAR |
ice pack |
$5.00 |
|||
5 ANZ |
tennis racquet |
$19.80 |
|||
9 ANZ |
volleyball net |
$20.00 |
|||
103 PRC |
frnt derailleur |
$20.00 |
|||
108 SHM |
crankset |
$45.00 |
|||
6 ANZ |
tennis ball |
$48.00 |
|||
305 HRO |
first-aid kit |
$48.00 |
|||
303 PRC |
socks |
$48.00 |
|||
311 SHM |
water gloves |
$48.00 |
|||
113 SHM |
18-spd, assmblc |
1 $685.90 |
|||
1 HSK |
baseball gloves |
$800.00 |
|||
8 ANZ |
volleyball |
$840.00 |
|||
4 HSK |
football |
$960.00 |
ORDER BY子句中的列的顺序十分重要,DESC关键字的位置也很重要。尽管下列查询中 的各语句在ORDER BY子句中包含相同的语句,但是每个语句产生的结果并不相同(没 有显示)。
图查询
SELECT * FROM stock ORDER BY manu_code, unit_price DESC;
SELECT * FROM stock ORDER BY unit_price, manu_code DESC;
SELECT * FROM stock ORDER BY manu_code DESC, unit_price;
SELECT * FROM stock ORDER BY unit_price DESC, manu_code;
3.2.3选择特定列
之前的章节显示了如何选择和排序表中所有的数据。然而,您经常希望看到的是一个或多 个特定列的数据。并且,公式是使用Projection和FROM子句指定列和表,并可以使用 ORDER BY子句按照升序或降序对数据进行排序。
如果想要操作orders表中的所有客户号,那么使用以下查询中的语句。
图:查询
SELECT customer_num FROM orders;
该结果显示了语句如何只选择orders表中customer_num列中的所有数据,并列出所有订单 上的客户号,包括重复的客户号。
图:查询结果