↑↓ 选择 ↵ 打开 ⌫ 改范围 完整检索页

pgsql.cc 提供对 postgresql.org 官网内容的中文翻译,由 Pigsty 团队维护。

受支持版本: 当前版本 (18) / 17 / 16 / 15 / 14
测试与开发版本: 19 / devel
不受支持的版本: 13 / 12 / 11 / 10 / 9.6 / 9.5 / 9.4 / 9.3 / 9.2 / 9.1 / 9.0 / 8.4 / 8.3 / 8.2 / 8.1 / 8.0 / 7.4 / 7.3 / 7.2 / 7.1 / 7.0 / 6.5 / 6.4
历史版本PostgreSQL 7.4 已于 2010 年 10 月结束社区维护,本页译文保留供仍在使用旧版本的读者参考。新系统请看当前版本。

SELECT

SELECT — 从表或视图中检索行

大纲

SELECT [ ALL | DISTINCT [ ON ( expression [, ...] ) ] ]
    * | expression [ AS output_name ] [, ...]
    [ FROM from_item [, ...] ]
    [ WHERE condition ]
    [ GROUP BY expression [, ...] ]
    [ HAVING condition [, ...] ]
    [ { UNION | INTERSECT | EXCEPT } [ ALL ] select ]
    [ ORDER BY expression [ ASC | DESC | USING operator ] [, ...] ]
    [ LIMIT { count | ALL } ]
    [ OFFSET start ]
    [ FOR UPDATE [ OF table_name [, ...] ] ]

where from_item can be one of:

    [ ONLY ] table_name [ * ] [ [ AS ] alias [ ( column_alias [, ...] ) ] ]
    ( select ) [ AS ] alias [ ( column_alias [, ...] ) ]
    function_name ( [ argument [, ...] ] ) [ AS ] alias [ ( column_alias [, ...] | column_definition [, ...] ) ]
    function_name ( [ argument [, ...] ] ) AS ( column_definition [, ...] )
    from_item [ NATURAL ] join_type from_item [ ON join_condition | USING ( join_column [, ...] ) ]

描述

SELECT 从一个或多个表中检索行。 SELECT 的一般处理过程如下:

  1. 所有FROM列表中的元素都会被计算。 (FROM列表中的每个元素都是一个真实或虚拟表。) 如果在FROM列表中指定了多个元素,则它们会被交叉连接在一起。 (参见下面的FROM 子句。)

  2. 如果指定了WHERE子句,则不满足条件的所有行将从输出中删除。 (请参见下面的WHERE Clause。)

  3. 如果指定了GROUP BY子句, 或者存在聚合函数调用, 输出将被组合成在一个或多个值上匹配的行组, 并计算聚合函数的结果。 如果存在HAVING子句, 它将消除不满足给定条件的组。(参见 GROUP BY Clause和 HAVING Clause。)

  4. 使用操作符UNION、INTERSECT和EXCEPT,可以把多条SELECT语句的输出合并成一个结果集。UNION操作符返回在一个或两个结果集中的所有行。INTERSECT操作符返回严格同时在两个结果集中的所有行。EXCEPT操作符返回在第一个结果集中但不在第二个结果集中的行。在这三种情况下,除非指定了 ALL,否则重复行都会被消除。(见下面的 UNION Clause、 INTERSECT Clause 和 EXCEPT Clause。)

  5. 实际输出行是使用每个选定行或行组的SELECT输出表达式计算的。 (参见下面的SELECT 列表。)

  6. 如果指定了ORDER BY子句,则返回的行按指定顺序排序。 如果没有给出ORDER BY,则按系统认为最快的顺序返回行。 (参见下面的ORDER BY 子句。)

  7. SELECT DISTINCT消除结果中的重复行。 SELECT DISTINCT ON会消除在所有指定表达式上匹配的行,只保留每组中的第一行。 SELECT ALL(默认)将返回所有候选行,包括重复行。 (参见下面的DISTINCT 子句。)

  8. 如果指定了LIMIT或OFFSET子句, SELECT语句只返回结果行的子集。(参见下面的LIMIT 子句。)

  9. FOR UPDATE子句使SELECT语句把选定的行锁定,防止并发更新。(见下面的FOR UPDATE 子句。)

你必须在一个表上拥有SELECT权限才能读取它的值。使用FOR UPDATE还要求UPDATE权限。

参数

FROM 子句

FROM 子句为 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必须用圆括号括起来,并且 必须为其提供别名。

function_name

函数调用可以出现在FROM子句中。(这对于返回结果集的函数尤其有用,但任何函数都可以使用。)其效果就像在这条SELECT命令执行期间,将函数的输出创建成了一张临时表。也可以使用别名。如果写了别名,还可以写一个列别名列表,为函数复合返回类型中的一个或多个属性提供替代名称。如果函数被定义为返回record数据类型,则必须给出别名或关键字AS,后面跟一个如下形式的列定义列表:( column_name data_type [, ... ] )。列定义列表必须与函数实际返回的列数和类型相匹配。

join_type

以下之一:

  • [ INNER ] JOIN

  • LEFT [ OUTER ] JOIN

  • RIGHT [ OUTER ] JOIN

  • FULL [ OUTER ] JOIN

  • CROSS JOIN

对于INNER和OUTER连接类型,必须指定一个连接条件,即NATURAL、ON join_condition或USING (join_column [, ...])三者中恰好之一。其含义见下文。对于CROSS JOIN,这些子句都不能出现。

JOIN 子句组合两个 FROM 项。如有必要可用圆括号确定嵌套的顺序。在没有圆括号时,JOIN 从左到右嵌套。在任何情况下,JOIN 的结合都比分隔 FROM 项的逗号更紧。

CROSS JOIN和INNER JOIN产生简单的笛卡尔积,与在FROM顶层列出这两个表得到的结果相同,但会受到连接条件(如果有)的限制。CROSS JOIN等价于INNER JOIN ON (TRUE),也就是说,没有行会被条件过滤掉。这些连接类型只是提供了一种方便的记法,因为它们所做的一切都可以用普通的FROM和WHERE完成。

LEFT OUTER JOIN返回已限定笛卡尔积中的所有行(即,通过其连接条件的所有组合行),外加左侧表中每一行的一个副本;对于这些行,不存在通过连接条件的右侧行。这样的左侧行会通过在右侧列中插入空值而扩展到连接表的完整宽度。注意,在决定哪些行有匹配项时,只考虑JOIN子句自身的条件;外层条件是在之后应用的。

相反,RIGHT OUTER JOIN返回所有连接后的行,再加上每个未匹配右侧行对应的一行 (左侧用空值扩展)。这只是一种记法上的便利,因为你可以通过交换左右表 将其改写成LEFT OUTER JOIN。

FULL OUTER JOIN返回所有连接后的行,再加上每个未匹配的左侧行(右侧用空值扩展),以及每个未匹配的右侧行(左侧用空值扩展)。

ON join_condition

join_condition 是一个表达式,其结果类型为 boolean(类似于 WHERE 子句),用于指定连接中哪些行被视为匹配。

USING ( join_column [, ...] )

一个形如USING ( a, b, ... )的子句是ON left_table.a = right_table.a AND left_table.b = right_table.b ...的简写。此外, USING意味着只有每对等价列中的一个会包含在连接输出中,而不是两者都包含。

NATURAL

NATURAL 是一个简写,表示一个列出两个表中所有同名列的 USING 列表。

WHERE Clause

可选的WHERE子句的形式

WHERE condition

其中condition 是任一计算得到boolean类型结果的表达式。任何不满足 这个条件的行都会从输出中被消除。如果用一行的实际值替换其中的 变量引用后,该表达式返回真,则该行符合条件。

GROUP BY Clause

可选的 GROUP BY 子句的一般形式为

GROUP BY expression [, ...]

GROUP BY会把所有在分组表达式上具有相同值的已选中 行压缩成单独一行。expression可以是输入列名、输出列 (SELECT列表项)的名称或序号或者由输入列 值构成的任意表达式。在出现歧义时,GROUP BY名称 将被解释为输入列名而不是输出列名。

聚合函数(如果使用了的话)会在组成每个组的所有行上进行计算,为每个组产生一个单独的值(而没有GROUP BY时,聚合会产生一个在所有被选中的行上计算出的单一值)。当存在GROUP BY时,SELECT列表表达式引用未分组的列是无效的,除非是在聚合函数内部,因为对一个未分组的列可能会有多个可能的返回值。

HAVING Clause

可选的HAVING子句的形式

HAVING condition

其中condition与 WHERE子句中指定的条件相同。

HAVING消除不满足该条件的分组行。 HAVING与WHERE不同: WHERE会在应用GROUP BY之前过滤个体行,而HAVING过滤由 GROUP BY创建的分组行。 condition中引用 的每一列都必须无歧义地引用某个分组列,除非该引用出现在聚合 函数中,或者该非分组列函数依赖于分组列。

UNION Clause

UNION 子句的一般形式是:

select_statement UNION [ ALL ] select_statement

select_statement 是不带 ORDER BY、LIMIT 或 FOR UPDATE 子句的任何 SELECT 语句。(如果用圆括号括起,ORDER BY 和 LIMIT 可以附加到子表达式上。不带圆括号时,这些子句将被认为应用于 UNION 的结果,而不是它的右侧输入表达式。)

UNION 操作符计算所涉及的 SELECT 语句返回的行的集合并集。如果一行出现在至少一个结果集中,它就在两个结果集的集合并集中。表示 UNION 的直接操作数的两个 SELECT 语句必须产生相同数量的列,并且对应的列必须是兼容的数据类型。

UNION 的结果不包含任何重复行,除非指定了 ALL 选项。ALL 阻止消除重复行。

同一 SELECT 语句中的多个 UNION 操作符从左到右求值,除非圆括号另有指示。

当前,FOR UPDATE不能为UNION的结果或UNION的任何输入指定。

INTERSECT Clause

INTERSECT 子句的一般形式是:

select_statement INTERSECT [ ALL ] select_statement

select_statement 是不带 ORDER BY、LIMIT 或 FOR UPDATE 子句的任何 SELECT 语句。

INTERSECT操作符计算相关 SELECT语句返回的行的交集。如果 一行同时出现在两个结果集中,它就在交集中。

INTERSECT 的结果不包含任何重复行,除非指定了 ALL 选项。带 ALL 时,在左表中有 m 个重复且在右表中有 n 个重复的行将在结果集中出现 min(m,n) 次。

同一 SELECT 语句中的多个 INTERSECT 操作符从左到右求值,除非圆括号另有指示。INTERSECT 比 UNION 绑定得更紧。也就是说,A UNION B INTERSECT C 将被读作 A UNION (B INTERSECT C)。

EXCEPT Clause

EXCEPT 子句的一般形式是:

select_statement EXCEPT [ ALL ] select_statement

select_statement 是不带 ORDER BY、LIMIT 或 FOR UPDATE 子句的任何 SELECT 语句。

EXCEPT操作符计算位于左侧 SELECT语句的结果中但不在右侧语句结果中的行集合。

EXCEPT 的结果不包含任何重复行,除非指定了 ALL 选项。带 ALL 时,在左表中有 m 个重复且在右表中有 n 个重复的行将在结果集中出现 max(m-n,0) 次。

同一 SELECT 语句中的多个 EXCEPT 操作符从左到右求值,除非圆括号另有指示。EXCEPT 与 UNION 绑定在同一级别。

SELECT 列表

SELECT列表(位于关键词 SELECT和FROM之间)指定构成 SELECT语句输出行的表达式。这些表达式 可以(并且通常确实会)引用FROM子句中计算得到的列。使用AS output_name子句可以为输出列指定另一个名称。这个名称主要用于给要显示的列做标记。它也可以用来在ORDER BY和GROUP BY子句中引用该列的值,但不能用在WHERE或HAVING子句中;在那里必须写出表达式。

可以在输出列表中写*来取代表达式,它是被选中 行的所有列的一种简写方式。还可以写 table_name.*,它 是只来自那个表的所有列的简写形式。

ORDER BY 子句

可选的 ORDER BY 子句的一般形式为:

ORDER BY expression [ ASC | DESC | USING operator ] [, ...]

expression 可以是输出列(SELECT 列表项)的名称或序号,也可以是由输入列值构成的任意表达式。

ORDER BY 子句使结果行按指定的表达式排序。如果两行按最左边的表达式相等,则按下一个表达式比较,依此类推。如果它们按所有指定的表达式都相等,则以依赖于实现顺序的顺序返回。

序号指的是输出列的顺序(从左至右)位置。这种特性可以为不具有唯一 名称的列定义一个顺序。这不是绝对必要的,因为总是可以使用 AS子句为输出列赋予一个名称。

也可以在ORDER BY子句中使用任意表达式,包括没 有出现在SELECT输出列表中的列。因此, 下面的语句是合法的:

SELECT name FROM distributors ORDER BY code;

这种特性的一个限制是一个应用在UNION、 INTERSECT或EXCEPT子句结果上的 ORDER BY只能指定输出列名称或序号,但不能指定表达式。

如果一个ORDER BY表达式是一个既匹配输出列名称又匹配 输入列名称的简单名称,ORDER BY将把它解读成输出列名 称。这与在同样情况下GROUP BY会做出的选择相反。这种 不一致是为了与 SQL 标准兼容。

可以在ORDER BY子句中任一表达式之后附加关键字 ASC(升序)或DESC(降序)。如果没有指定, ASC被假定为默认值。或者,可以在USING 子句中指定一个特定的排序操作符名称。一个排序操作符必须是某个 B-树操作符族的小于或者大于成员。ASC通常等价于 USING <而DESC通常等价于 USING >(但是一种用户定义数据类型的创建者可以 准确地定义默认排序顺序是什么,并且它可能会对应于其他名称的操作符)。

空值的排序高于任何其他值。换句话说,在升序排序时,空值排在最后; 在降序排序时,空值排在最前。

字符串数据按照数据库集簇初始化时建立的区域相关排序顺序来排序。

LIMIT 子句

该 LIMIT 子句由两个独立的子句组成:

LIMIT { count | ALL }
OFFSET start

count 指定最多返回多少行,而 start 指定开始返回行之前要跳过的行数。如果两者都指定,则先跳过 start 行,然后开始计数并返回 count 行。

使用 LIMIT 时,最好使用把结果行约束为唯一顺序的 ORDER BY 子句。否则你会得到查询行的一个不可预测的子集——你可能要的是第十到第二十行,但是按什么顺序的第十到第二十行?除非指定 ORDER BY,否则你不知道顺序。

查询规划器在生成一个查询计划时会考虑LIMIT,因此 根据你使用的LIMIT和OFFSET,你很可能 得到不同的计划(得到不同的行序)。所以,使用不同的 LIMIT/OFFSET值来选择一个查询结果的 不同子集将会给出不一致的结果,除非你 用ORDER BY强制一种可预测的结果顺序。这不是一个 缺陷,它是 SQL 不承诺以任何特定顺序(除非使用 ORDER BY来约束顺序)给出一个查询结果这一事实造 成的必然后果。

DISTINCT 子句

如果指定了SELECT DISTINCT,所有重复的行会被从结果 集中移除(为每一组重复的行保留一行)。SELECT ALL则 指定相反的行为:所有行都会被保留,这也是默认情况。

DISTINCT ON ( expression [, ...] ) 只保留给定表达式求值相等的每组行中的第一行。DISTINCT ON 表达式使用与 ORDER BY 相同的规则解释(见上文)。注意,除非用 ORDER BY 保证想要的行出现在最前,否则每个集合的“第一行”是不可预测的。例如,

SELECT DISTINCT ON (location) location, time, report
    FROM weather_reports
    ORDER BY location, time DESC;

检索每个位置的最新天气报告。但如果我们没有用 ORDER BY 强制每个位置的时间值降序,我们就会得到每个位置一个不可预测时间的报告。

DISTINCT ON表达式必须匹配最左边的 ORDER BY表达式。ORDER BY子句通常 将包含额外的表达式,这些额外的表达式用于决定在每一个 DISTINCT ON分组内行的优先级。

FOR UPDATE 子句

FOR UPDATE 子句的形式如下:

FOR UPDATE [ OF table_name [, ...] ]

FOR UPDATE使SELECT语句检索到的行像被更新一样被锁定。这防止其他事务在当前事务结束之前修改或删除它们。也就是说,其他事务对这些行尝试UPDATE、DELETE或SELECT FOR UPDATE时将被阻塞,直到当前事务结束。此外,如果来自另一个事务的UPDATE、DELETE或SELECT FOR UPDATE已经锁定了被选中的一行或多行,SELECT FOR UPDATE将等待那个事务完成,然后锁定并返回更新后的行(如果该行已被删除,则不返回行)。进一步的讨论见第 12 章。

如果在FOR UPDATE中命名了特定的表,那么只有来自那些表的行会被锁定;SELECT中用到的任何其他表都只是被照常读取。

在返回的行无法清楚地与各个表行对应起来的上下文中,不能使用FOR UPDATE;例如它不能与聚合一起使用。

FOR UPDATE 为了与 7.3 之前的 PostgreSQL 版本兼容,可以出现在 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
 ...

要对所有电影的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

对所有影片的 len 列求和,按 kind 分组,并显示少于 5 小时的组总计:

SELECT kind, sum(len) AS total
    FROM films
    GROUP BY kind
    HAVING sum(len) < interval '5 hours';

   kind   | total
----------+-------
 Comedy   | 02:58
 Romantic | 04:38

下面两个示例都是根据第二列(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

接下来的示例展示了如何得到表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

这个例子展示如何在 FROM 子句中使用函数,包括带和不带列定义列表两种情况:

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

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

兼容性

当然,SELECT语句与 SQL 标准兼容。 但它也有一些扩展和缺失的特性。

省略的 FROM 子句

PostgreSQL 允许省略 FROM 子句。它可以直接用于计算简单表达式的结果:

SELECT 2+2;

 ?column?
----------
        4

其他一些 SQL 数据库必须引入一个只有一行的虚拟表,才能从该表执行 SELECT。

一个不太明显的用法是缩写对表的普通 SELECT:

SELECT distributors.* WHERE distributors.name = 'Westward';

 did |   name
-----+----------
 108 | Westward

这之所以可行,是因为对在 SELECT 语句的其他部分中被引用但在 FROM 中未提及的每个表,都会添加一个隐式的 FROM 项。

虽然这是一个方便的缩写,但很容易误用。例如,命令

SELECT distributors.* FROM distributors d;

很可能是一个错误;用户很可能想要的是

SELECT d.* FROM distributors d;

而不是他将实际得到的无约束连接

SELECT distributors.* FROM distributors d, distributors distributors;

。为了帮助检测这类错误,如果在也包含显式 FROM 子句的 SELECT 语句中使用了隐式 FROM 特性,PostgreSQL 会发出警告。此外,可以通过把 ADD_MISSING_FROM 参数设置为 false 来禁用隐式 FROM 特性。

AS 关键字

在 SQL 标准中,可选关键词AS只是一个噪音词,可以省略它而不影响含义。PostgreSQL解析器在重命名输出列时要求这个关键词,因为类型可扩展性特性使得没有它就会出现解析歧义。不过,AS在FROM项中是可选的。

GROUP BY 和 ORDER BY 可用的命名空间

在 SQL92 标准中,ORDER BY 子句只能使用结果列名或编号,而 GROUP BY 子句只能使用基于输入列名的表达式。PostgreSQL 扩展了这两个子句,允许另一种选择(但在有歧义时使用标准的解释)。PostgreSQL 还允许两个子句指定任意表达式。注意,表达式中出现的名称总是被当作输入列名,而不是结果列名。

SQL99 使用一个略有不同的定义,它与 SQL92 不完全向上兼容。但在大多数情况下,PostgreSQL 对 ORDER BY 或 GROUP BY 表达式的解释与 SQL99 相同。

非标准子句

DISTINCT ON、LIMIT和OFFSET子句未在 SQL 标准中定义。

提交更正

译文有误、术语不当或页面显示问题,请到译文仓库 pgsty/pgdoc 报告译文问题。 英文原文本身的问题,请在当前版本的对应页面向上游反馈;上游不再修订已结束维护的版本。