pgsql.cc 提供对 postgresql.org 官网内容的中文翻译,由 Pigsty 团队维护。
SELECT — 从表或视图中检索行
SELECT [ ALL | DISTINCT [ ON (expression[, ...] ) ] ] * |expression[ ASoutput_name] [, ...] [ FROMfrom_item[, ...] ] [ WHEREcondition] [ GROUP BYexpression[, ...] ] [ HAVINGcondition[, ...] ] [ { UNION | INTERSECT | EXCEPT } [ ALL ]select] [ ORDER BYexpression[ ASC | DESC | USINGoperator] [, ...] ] [ LIMIT {count| ALL } ] [ OFFSETstart] [ FOR UPDATE [ OFtablename[, ...] ] ] wherefrom_itemcan be: [ ONLY ]table_name[ * ] [ [ AS ]alias[ (column_alias_list) ] ] | (select) [ AS ]alias[ (column_alias_list) ] |table_function_name( [argument[, ...] ] ) [ AS ]alias[ (column_alias_list|column_definition_list) ] |table_function_name( [argument[, ...] ] ) AS (column_definition_list) |from_item[ NATURAL ]join_typefrom_item[ ONjoin_condition| USING (join_column_list) ]
expression表的列名或一个表达式。
output_name用 AS 子句为输出列指定另一个名称。此名称主要用于为列提供一个便于显示的标签。它也可以用于在 ORDER BY 和 GROUP BY 子句中引用该列的值。但 output_name 不能用于 WHERE 或 HAVING 子句;应改写该表达式。
from_item一个表引用、子 SELECT、表函数或 JOIN 子句。细节见下文。
condition一个结果为真或假的布尔表达式。见下面的 WHERE 和 HAVING 子句描述。
select一个除 ORDER BY、LIMIT/OFFSET 和 FOR UPDATE 子句外具有所有特性的 select 语句(当 select 用圆括号括起时,甚至这些也可以使用)。
FROM 项可以包含:
table_name一个现有表或视图的名称(可以选择带模式限定)。如果指定了 ONLY,则只扫描该表。如果未指定 ONLY,则扫描该表及其所有后代表(如果有)。 * 可以附加到表名后面以指示要扫描后代表,但在当前版本中这是默认行为。(在 7.1 之前的版本中,ONLY 是默认行为。)默认行为可以通过更改 SQL_INHERITANCE 配置选项来修改。
alias包含别名的 FROM 项的替代名称。别名用于简洁或消除自连接(同一表被扫描多次)的歧义。提供别名时,它完全隐藏表或表函数的实际名称;例如给定 FROM foo AS f, SELECT 的其余部分必须把这个 FROM 项引用为 f 而不是 foo. 如果写了别名,还可以写一个列别名列表来为该表的一列或多列提供替代名称。
select子 SELECT 可以出现在 FROM 子句中。它的行为就像其输出在此单条 SELECT 命令期间被创建为临时表一样。注意子 SELECT 必须用圆括号括起,并且必须 为它提供别名。
table function表函数可以出现在 FROM 子句中。它的行为就像其输出在此单条 SELECT 命令期间被创建为临时表一样。也可以使用别名。如果写了别名,还可以写一个列别名列表来为该表函数的一列或多列提供替代名称。如果表函数被定义为返回 record 数据类型,则必须有别名或关键字 AS,后跟如下形式的列定义列表 ( column_name data_type [, ... ] ). 列定义列表必须与该函数返回的列的实际数量和类型匹配。
join_type下列之一: [ INNER ] JOIN, LEFT [ OUTER ] JOIN, RIGHT [ OUTER ] JOIN, FULL [ OUTER ] JOIN, or CROSS JOIN. 对于 INNER 和 OUTER 连接类型,必须恰好出现 NATURAL、 ON join_condition, or USING ( join_column_list ) 之一。对于 CROSS JOIN,这些项都不能出现。
join_condition一个限定条件。它类似于 WHERE 条件,只是它只应用于在此 JOIN 子句中连接的两个 from_item。
join_column_listUSING 列列表 ( a, b, ... ) 是 ON 条件 left_table.a = right_table.a AND left_table.b = right_table.b ... 的简写。
由查询说明产生的完整行集合。
count查询返回的行数。
SELECT 将从一个或多个表返回行。选择的候选是满足 WHERE 条件的行;如果省略 WHERE,则所有行都是候选。 (See WHERE 子句.)
实际上,返回的行并不直接是 FROM/WHERE/GROUP BY/HAVING 子句产生的行;输出行是通过对每个选中行计算 SELECT 输出表达式而形成的。 * 可以作为所有选中行的列的简写在输出列表中写。还可以写 table_name.* 作为只来自该表的列的简写。
DISTINCT 将从结果中消除重复行。 ALL(默认)将返回所有候选行, 包括重复行。
DISTINCT ON 消除在所有指定表达式上匹配的行,只保留每组重复行中的第一行。DISTINCT ON 表达式使用与 ORDER BY 项相同的规则解释;见下文。 注意,除非用 ORDER BY 保证想要的 行出现在最前,否则每个集合的“第一行”是不可预测的。 例如,
SELECT DISTINCT ON (location) location, time, report
FROM weatherReports
ORDER BY location, time DESC;
它取回每个位置的最新天气报告。但如果 我们没有用 ORDER BY 强制每个位置的时间值降序, 我们就会得到每个位置一个不可预测时间的报告。
GROUP BY 子句允许用户把一个表划分为在一个或多个值上匹配的行组。 (See GROUP BY 子句.)
HAVING 子句允许只选择满足指定条件的那些行组。 (See HAVING 子句.)
ORDER BY 子句使返回的行按指定的顺序排序。如果没有给出 ORDER BY,行按系统认为产生成本最低的任何顺序返回。 (See ORDER BY 子句.)
SELECT 查询可以用 UNION、INTERSECT 和 EXCEPT 操作符组合。必要时使用圆括号来确定这些操作符的顺序。
UNION 操作符计算所涉及查询返回的行的集合。除非指定 ALL,否则消除重复行。 (See UNION 子句.)
INTERSECT 操作符计算两个查询共同的行。除非指定 ALL,否则消除重复行。 (See INTERSECT 子句.)
EXCEPT 操作符计算第一个查询返回的行,但不返回第二个查询的行。除非指定 ALL,否则消除重复行。 (See EXCEPT 子句.)
LIMIT 子句允许把查询产生的行的一个子集返回给用户。 (See LIMIT 子句.)
FOR UPDATE 子句使 SELECT 语句对选中的行加锁以防止并发更新。
你必须对一个表拥有 SELECT 权限才能读取它的值(见 GRANT/REVOKE 语句)。使用 FOR UPDATE 还需要 UPDATE 权限。
FROM 子句为 SELECT 指定一个或多个源表。如果指定多个源,结果在概念上是所有源中所有行的笛卡尔积——但通常会添加限定条件把返回的行限制为笛卡尔积的一个小子集。
当 FROM 项是一个简单表名时,它隐式地包括该表的子表(继承子女)的行。ONLY 将抑制该表的子表的行。在 PostgreSQL 7.1 之前这是默认结果,添加子表是通过在表名后面附加 * 来完成的。这一旧行为可以通过命令 SET SQL_Inheritance TO OFF 获得。
FROM 项也可以是用圆括号括起的子 SELECT(注意子 SELECT 必须有别名子句!)。这是一个极其方便的特性,因为它是在单个查询中获得多级分组、聚合或排序的唯一方式。
FROM 项可以是表函数(通常是返回多行和/或多列的函数,但实际上任何函数都可以)。以给定的参数值调用该函数,然后其输出被当作表一样扫描。
在某些情况下,定义可以根据调用方式返回不同列集的表函数是有用的。为此,表函数可以声明为返回伪类型 record。当这样的函数用于 FROM 中时,它后面必须有别名或单独的关键字 AS,然后是圆括号括起的列名和类型列表。这提供了查询时的组合类型定义。组合类型定义必须与该函数返回的实际组合类型匹配,否则将在运行时报告错误。
最后,FROM 项可以是 JOIN 子句,它组合两个更简单的 FROM 项。(必要时使用圆括号来确定嵌套顺序。)
CROSS JOIN 或 INNER JOIN 是简单的笛卡尔积,与在 FROM 顶层列出两个项所得到的相同。CROSS JOIN 等价于 INNER JOIN ON (TRUE),即没有行被限定移除。这些连接类型只是记法上的便利,因为它们没有做任何用普通 FROM 和 WHERE 做不到的事。
LEFT OUTER JOIN 返回限定笛卡尔积中的所有行(即通过其 ON 条件的所有组合行),再加上左表中每一个没有通过 ON 条件的右行的行的一个副本。这个左表行通过为右表列插入空值扩展到被连接表的全宽度。注意,在决定哪些行有匹配时只考虑 JOIN 自己的 ON 或 USING 条件。外层的 ON 或 WHERE 条件在此之后应用。
相反, RIGHT OUTER JOIN 返回所有连接后的行,再加上每个未匹配右侧行对应的一行 (左侧用空值扩展)。这只是一种记法上的便利,因为你可以通过交换左右表 将其改写成 LEFT OUTER JOIN 。
FULL OUTER JOIN 返回所有连接后的行,再加上每个未匹配的左侧行(右侧用空值扩展),以及每个未匹配的右侧行(左侧用空值扩展)。
对于除 CROSS JOIN 外的所有 JOIN 类型,必须恰好写下列之一: ON join_condition, USING ( join_column_list ), or NATURAL. ON 是最一般的情况:可以写涉及要连接的两个表的任何限定表达式。 USING 列列表 ( a, b, ... ) 是 ON 条件 left_table.a = right_table.a AND left_table.b = right_table.b ... 的简写。 另外,USING 意味着只有每对等价列中的一个会包含在 JOIN 输出中,而不是两者都包含。NATURAL 是 一个 USING 列表的简写,该列表列出表中所有同名的列。
可选的 WHERE 条件具有如下一般形式:
WHERE boolean_expr
boolean_expr 可以由任何求值为布尔值的表达式组成。在许多情况下,此表达式会是:
expr cond_op expr
或
log_op expr
其中 cond_op 可以是 =、<、<=、>、>= 或 <> 之一, 或像 ALL、ANY、IN、LIKE 这样的条件操作符,或 本地定义的操作符, 而 log_op 可以是 AND、OR、NOT 之一。 SELECT 将忽略所有 WHERE 条件不返回 TRUE 的行。
GROUP BY 指定通过应用此子句导出的分组表:
GROUP BY expression [, ...]
GROUP BY 把在分组列上共享相同值的所有选中行压缩为单行。聚合函数(如果使用了的话) 会在组成每个组的所有行上进行计算,为每个组产生一个 单独的值(而没有 GROUP BY 时,聚合会产生 一个在所有被选中的行上计算出的单一值)。当存在 GROUP BY 时,SELECT 输出表达式引用 未分组的列是无效的,除非是在聚合函数内部,因为 对一个未分组的列可能会有多个可能的返回值。
GROUP BY 项可以是输入列名、输出列(SELECT 表达式)的名称或序号,也可以是由输入列值构成的任意表达式。在有歧义时,GROUP BY 名称将被解释为输入列名而不是输出列名。
可选的 HAVING 条件具有如下一般形式:
HAVING boolean_expr
其中 boolean_expr 与为 WHERE 子句指定的相同。
HAVING 指定通过消除不满足 boolean_expr 的组行而导出的分组表。HAVING 与 WHERE 不同:WHERE 在应用 GROUP BY 之前过滤单独的行,而 HAVING 过滤 GROUP BY 创建的组行。
boolean_expr 中引用的每一列都应无歧义地引用一个分组列,除非该引用出现在聚合函数内。
ORDER BYexpression[ ASC | DESC | USINGoperator] [, ...]
ORDER BY 项可以是输出列(SELECT 表达式)的名称或序号,也可以是由输入列值构成的任意表达式。在有歧义时,ORDER BY 名称将被解释为输出列名。
序号指结果列的(从左到右的)位置。此特性使得可以基于没有唯一名称的列定义排序。 这永远不是绝对必要的,因为总是可以用 AS 子句 为结果列赋予一个名称,例如:
SELECT title, date_prod + 1 AS newlen FROM films ORDER BY newlen;
也可以按任意表达式 ORDER BY(对 SQL92 的扩展),包括不出现在 SELECT 结果列表中的字段。 因此下面的语句是合法的:
SELECT name FROM distributors ORDER BY code;
A limitation of this feature is that an ORDER BY clause applying to the result of a UNION, INTERSECT, or EXCEPT query may only specify an output column name or number, not an expression.
注意,如果 ORDER BY 项是一个既匹配结果列名又匹配输入列名的简单名称,ORDER BY 将把它解释为结果列名。这与 GROUP BY 在相同情况下所作的选择相反。这种不一致是 SQL92 标准规定的。
还可以在 ORDER BY 子句中的每个列名后面添加关键字 DESC(降序)或 ASC(升序)。如果未指定,默认为 ASC。或者,可以指定一个特定的排序操作符 名称。ASC 等价于 USING < 而 DESC 等价于 USING >。
空值在域中排序高于任何其他值。换句话说,按升序排序时空值排在最后,按降序排序时空值排在最前。
字符类型的数据按照初始化数据库集群时建立的特定区域设置的排序规则排序。
table_queryUNION [ ALL ]table_query[ ORDER BYexpression[ ASC | DESC | USINGoperator] [, ...] ] [ LIMIT {count| ALL } ] [ OFFSETstart]
where table_query 指定不带 ORDER BY、LIMIT 或 FOR UPDATE 子句的任何 select 表达式。(如果用圆括号括起, ORDER BY 和 LIMIT 可以附加到子表达式上。不带圆括号时,这些子句 将被认为应用于 UNION 的结果,而不是它的右侧 输入表达式。)
UNION 操作符计算所涉及查询返回的行的集合(集合并集)。表示 UNION 的直接操作数的两个 SELECT 语句必须产生相同数量的列,并且对应的列必须是兼容的数据类型。
UNION 的结果不包含任何重复行,除非指定了 ALL 选项。ALL 阻止消除重复行。
同一 SELECT 语句中的多个 UNION 操作符从左到右求值,除非圆括号另有指示。
目前,不能对 UNION 的结果或 UNION 的输入指定 FOR UPDATE。
table_queryINTERSECT [ ALL ]table_query[ ORDER BYexpression[ ASC | DESC | USINGoperator] [, ...] ] [ LIMIT {count| ALL } ] [ OFFSETstart]
where table_query 指定不带 ORDER BY、LIMIT 或 FOR UPDATE 子句的任何 select 表达式。
INTERSECT 类似于 UNION,只是它只产生在两个查询输出中都出现的行,而不是在任一输出中出现的行。
INTERSECT 的结果不包含任何重复行,除非指定了 ALL 选项。带 ALL 时, 在 L 中有 m 个重复且在 R 中有 n 个重复的行将出现 min(m,n) 次。
同一 SELECT 语句中的多个 INTERSECT 操作符从左到右求值,除非圆括号另有指示。INTERSECT 比 UNION 绑定得更紧——也就是说,除非圆括号另有指定,A UNION B INTERSECT C 将被读作 A UNION (B INTERSECT C)。
table_queryEXCEPT [ ALL ]table_query[ ORDER BYexpression[ ASC | DESC | USINGoperator] [, ...] ] [ LIMIT {count| ALL } ] [ OFFSETstart]
where table_query 指定不带 ORDER BY、LIMIT 或 FOR UPDATE 子句的任何 select 表达式。
EXCEPT 类似于 UNION,只是它只产生在左查询输出中出现而在右查询输出中不出现的行。
EXCEPT 的结果不包含任何重复行,除非指定了 ALL 选项。带 ALL 时, 在 L 中有 m 个重复且在 R 中有 n 个重复的行将出现 max(m-n,0) 次。
同一 SELECT 语句中的多个 EXCEPT 操作符从左到右求值,除非圆括号另有指示。EXCEPT 与 UNION 绑定在同一级别。
LIMIT { count | ALL }
OFFSET start
其中 count 指定返回的最大行数,start 指定开始返回行之前要跳过的行数。
LIMIT 允许只取回由查询其余部分产生的行的一部分。如果给出了限制数,则返回不超过那么多的行。如果给出了偏移,则在开始返回行之前跳过那么多的行。
使用 LIMIT 时,最好使用把结果行约束为唯一顺序的 ORDER BY 子句。否则你会得到查询行的一个不可预测的子集——你可能要的是第十到第二十行,但是按什么顺序的第十到第二十行?除非指定 ORDER BY,否则你不知道顺序。
从 PostgreSQL 7.0 起,查询优化器在生成查询计划时会把 LIMIT 考虑在内,所以很可能根据 LIMIT 和 OFFSET 的不同取值得到不同的计划(产生不同的行顺序)。因此,使用不同的 LIMIT/OFFSET 值选择查询结果的不同子集会得到不一致的结果,除非用 ORDER BY 强制可预测的结果顺序。这不是缺陷;这是 SQL 不承诺以任何特定顺序交付查询结果(除非用 ORDER BY 约束顺序)这一事实的固有后果。
FOR UPDATE [ OF tablename [, ...] ]
FOR UPDATE 使查询取回的行被像要更新一样锁定。这防止其他事务在当前事务结束之前修改或删除它们;也就是说,其他事务对这些行尝试 UPDATE、DELETE 或 SELECT FOR UPDATE 将被阻塞直到当前事务结束。此外,如果来自另一事务的 UPDATE、DELETE 或 SELECT FOR UPDATE 已经锁定了选中的一行或多行,SELECT FOR UPDATE 将等待另一事务完成,然后锁定并返回更新后的行(如果该行被删除则不返回行)。进一步的讨论见用户指南的并发章节。
如果在 FOR UPDATE 中命名了特定的表,那么只有来自那些表的行会被锁定; SELECT 中用到的任何其他表都只是被照常读取。
在返回的行无法清楚地与各个表行对应起来的上下文中,不能使用 FOR UPDATE ;例如它不能与聚合一起使用。
为了与 7.3 之前的应用兼容,FOR UPDATE 可以出现在 LIMIT 之前。但它实际上在 LIMIT 之后执行,所以推荐把它写在那里。
把表 films 与表 distributors 连接:
SELECT f.title, f.did, d.name, f.date_prod, f.kind
FROM distributors d, films f
WHERE f.did = d.did
title | did | name | date_prod | kind
---------------------------+-----+------------------+------------+----------
The Third Man | 101 | British Lion | 1949-12-23 | Drama
The African Queen | 101 | British Lion | 1951-08-11 | Romantic
Une Femme est une Femme | 102 | Jean Luc Godard | 1961-03-12 | Romantic
Vertigo | 103 | Paramount | 1958-11-14 | Action
Becket | 103 | Paramount | 1964-02-03 | Drama
48 Hrs | 103 | Paramount | 1982-10-22 | Action
War and Peace | 104 | Mosfilm | 1967-02-12 | Drama
West Side Story | 105 | United Artists | 1961-01-03 | Musical
Bananas | 105 | United Artists | 1971-07-13 | Comedy
Yojimbo | 106 | Toho | 1961-06-16 | Drama
There's a Girl in my Soup | 107 | Columbia | 1970-06-11 | Comedy
Taxi Driver | 107 | Columbia | 1975-05-15 | Action
Absence of Malice | 107 | Columbia | 1981-11-15 | Action
Storia di una donna | 108 | Westward | 1970-08-15 | Romantic
The King and I | 109 | 20th Century Fox | 1956-08-11 | Musical
Das Boot | 110 | Bavaria Atelier | 1981-11-11 | Drama
Bed Knobs and Broomsticks | 111 | Walt Disney | | Musical
(17 rows)
对所有影片的 len 列求和并按 kind 分组:
SELECT kind, SUM(len) AS total FROM films GROUP BY kind; kind | total ----------+------- Action | 07:34 Comedy | 02:58 Drama | 14:28 Musical | 06:42 Romantic | 04:38 (5 rows)
对所有影片的 len 列求和,按 kind 分组,并显示少于 5 小时的组总计:
SELECT kind, SUM(len) AS total
FROM films
GROUP BY kind
HAVING SUM(len) < INTERVAL '5 hour';
kind | total
----------+-------
Comedy | 02:58
Romantic | 04:38
(2 rows)
下面两个例子是按照第二列(name)的内容对各个结果排序的相同方式:
SELECT * FROM distributors ORDER BY name; SELECT * FROM distributors ORDER BY 2; did | name -----+------------------ 109 | 20th Century Fox 110 | Bavaria Atelier 101 | British Lion 107 | Columbia 102 | Jean Luc Godard 113 | Luso films 104 | Mosfilm 103 | Paramount 106 | Toho 105 | United Artists 111 | Walt Disney 112 | Warner Bros. 108 | Westward (13 rows)
这个例子展示如何获得表 distributors 和 actors 的并集,把结果限制为每个表中以字母 W 开头的行。只需要不重复的行,所以省略了 ALL 关键字:
distributors: actors:
did | name id | name
-----+-------------- ----+----------------
108 | Westward 1 | Woody Allen
111 | Walt Disney 2 | Warren Beatty
112 | Warner Bros. 3 | Walter Matthau
... ...
SELECT distributors.name
FROM distributors
WHERE distributors.name LIKE 'W%'
UNION
SELECT actors.name
FROM actors
WHERE actors.name LIKE 'W%';
name
----------------
Walt Disney
Walter Matthau
Warner Bros.
Warren Beatty
Westward
Woody Allen
这个例子展示如何使用表函数,包括带和不带列定义列表两种情况。
distributors: did | name -----+-------------- 108 | Westward 111 | Walt Disney 112 | Warner Bros. ... CREATE FUNCTION distributors(int) RETURNS SETOF distributors AS ' SELECT * FROM distributors WHERE did = $1; ' LANGUAGE SQL; SELECT * FROM distributors(111); did | name -----+------------- 111 | Walt Disney (1 row) CREATE FUNCTION distributors_2(int) RETURNS SETOF RECORD AS ' SELECT * FROM distributors WHERE did = $1; ' LANGUAGE SQL; SELECT * FROM distributors_2(111) AS (f1 int, f2 text); f1 | f2 -----+------------- 111 | Walt Disney (1 row)
PostgreSQL 允许在查询中省略 FROM 子句。此特性是从最初的 PostQUEL 查询语言保留下来的。它有一个直接的用途:计算简单表达式的结果:
SELECT 2+2;
?column?
----------
4
一些其他 SQL 数据库做不到这一点,除非引入一个单行的哑表来从中做 SELECT。一个不太明显的用法是缩写对一个或多个表的普通 SELECT:
SELECT distributors.* WHERE distributors.name = 'Westward'; did | name -----+---------- 108 | Westward
这之所以可行,是因为对查询中引用但在 FROM 中未提及的每个表, 都会添加一个隐式的 FROM 项。虽然这是一个方便的 缩写,但很容易误用。例如,查询
SELECT distributors.* FROM distributors d;
很可能是笔误;用户最可能想要的是
SELECT d.* FROM distributors d;
而不是他实际会得到的无约束连接
SELECT distributors.* FROM distributors d, distributors distributors;
为了帮助检测这类错误,PostgreSQL 7.1 及以后版本在查询同时使用了隐式 FROM 特性和显式 FROM 子句时将发出警告。
表函数特性是 PostgreSQL 的扩展。
在 SQL92 标准中,可选的关键字 AS 只是无意义的噪音,可以省略而不影响含义。PostgreSQL 解析器在重命名输出列时要求这个关键字,因为类型可扩展特性在此上下文中会导致解析歧义。不过 AS 在 FROM 项中是可选的。
DISTINCT ON 短语不是 SQL92 的一部分。LIMIT 和 OFFSET 也不是。
在 SQL92 中,ORDER BY 子句只能使用结果列名或编号,而 GROUP BY 子句只能使用输入列名。 PostgreSQL 对这两个子句都做了扩展,允许也使用另一种选择 (但在有歧义时采用标准的解释)。 PostgreSQL 还允许两个子句指定任意表达式。注意,表达式中出现的名称 将总是被当作输入列名,而不是结果列名。
SQL92 的 UNION/INTERSECT/EXCEPT 语法允许一个附加的 CORRESPONDING BY 选项:
table_queryUNION [ALL] [CORRESPONDING [BY (column[,...])]]table_query
PostgreSQL 不支持 CORRESPONDING BY 子句。
译文有误、术语不当或页面显示问题,请到译文仓库 pgsty/pgdoc 报告译文问题。 英文原文本身的问题,请在当前版本的对应页面向上游反馈;上游不再修订已结束维护的版本。