On this page
Note
SELECT
SELECT,TABLE 和 WITH —从表或视图中检索行
Synopsis
[ WITH [ RECURSIVE ] with_query [, ...] ]
SELECT [ ALL | DISTINCT [ ON ( expression [, ...] ) ] ]
[ * | expression [ [ AS ] output_name ] [, ...] ]
[ FROM from_item [, ...] ]
[ WHERE condition ]
[ GROUP BY grouping_element [, ...] ]
[ HAVING condition [, ...] ]
[ WINDOW window_name AS ( window_definition ) [, ...] ]
[ { UNION | INTERSECT | EXCEPT } [ ALL | DISTINCT ] select ]
[ ORDER BY expression [ ASC | DESC | USING operator ] [ NULLS { FIRST | LAST } ] [, ...] ]
[ LIMIT { count | ALL } ]
[ OFFSET start [ ROW | ROWS ] ]
[ FETCH { FIRST | NEXT } [ count ] { ROW | ROWS } ONLY ]
[ FOR { UPDATE | NO KEY UPDATE | SHARE | KEY SHARE } [ OF table_name [, ...] ] [ NOWAIT | SKIP LOCKED ] [...] ]
where from_item can be one of:
[ ONLY ] table_name [ * ] [ [ AS ] alias [ ( column_alias [, ...] ) ] ]
[ TABLESAMPLE sampling_method ( argument [, ...] ) [ REPEATABLE ( seed ) ] ]
[ LATERAL ] ( select ) [ AS ] alias [ ( column_alias [, ...] ) ]
with_query_name [ [ AS ] alias [ ( column_alias [, ...] ) ] ]
[ LATERAL ] function_name ( [ argument [, ...] ] )
[ WITH ORDINALITY ] [ [ AS ] alias [ ( column_alias [, ...] ) ] ]
[ LATERAL ] function_name ( [ argument [, ...] ] ) [ AS ] alias ( column_definition [, ...] )
[ LATERAL ] function_name ( [ argument [, ...] ] ) AS ( column_definition [, ...] )
[ LATERAL ] ROWS FROM( function_name ( [ argument [, ...] ] ) [ AS ( column_definition [, ...] ) ] [, ...] )
[ WITH ORDINALITY ] [ [ AS ] alias [ ( column_alias [, ...] ) ] ]
from_item [ NATURAL ] join_type from_item [ ON join_condition | USING ( join_column [, ...] ) ]
and grouping_element can be one of:
( )
expression
( expression [, ...] )
ROLLUP ( { expression | ( expression [, ...] ) } [, ...] )
CUBE ( { expression | ( expression [, ...] ) } [, ...] )
GROUPING SETS ( grouping_element [, ...] )
and with_query is:
with_query_name [ ( column_name [, ...] ) ] AS ( select | values | insert | update | delete )
TABLE [ ONLY ] table_name [ * ]
Description
SELECT
从零个或多个表中检索行。 SELECT
的一般处理如下:
计算
WITH
列表中的所有查询。这些有效地用作可以在FROM
列表中引用的临时表。在FROM
中多次引用的WITH
查询仅计算一次。 (请参见下面的WITH Clause。)计算
FROM
列表中的所有元素。 (FROM
列表中的每个元素都是真实表或虚拟表.)如果在FROM
列表中指定了多个元素,则它们将交叉连接在一起。 (请参见下面的FROM Clause。)如果指定了
WHERE
子句,将从输出中消除所有不满足条件的行。 (请参见下面的WHERE Clause。)如果指定了
GROUP BY
子句,或者有聚合函数调用,则将输出合并为与一个或多个值匹配的行组,并计算聚合函数的结果。如果存在HAVING
子句,它将消除不满足给定条件的组。 (请参见下面的按条款分组和HAVING Clause。)对于每个选定的行或行组,使用
SELECT
输出表达式来计算实际的输出行。 (请参见下面的SELECT List。)SELECT DISTINCT
从结果中消除重复的行。SELECT DISTINCT ON
消除与所有指定表达式匹配的行。SELECT ALL
(默认值)将返回所有候选行,包括重复项。 (请参见下面的DISTINCT Clause。)使用运算符
UNION
,INTERSECT
和EXCEPT
,可以组合多个SELECT
语句的输出以形成单个结果集。UNION
运算符返回一个或两个结果集中的所有行。INTERSECT
运算符返回严格位于两个结果集中的所有行。EXCEPT
运算符返回第一个结果集中的行,而不是第二个结果集中的行。在所有三种情况下,除非指定了ALL
,否则消除了重复的行。可以添加噪声字DISTINCT
以明确指定消除重复的行。请注意,尽管SELECT
本身是默认值,但DISTINCT
是此处的默认行为。 (请参见下面的UNION Clause,INTERSECT Clause和EXCEPT Clause。)如果指定了
ORDER BY
子句,则返回的行将以指定的 Sequences 排序。如果未提供ORDER BY
,则以系统认为最快的 Sequences 返回行。 (请参见下面的按条款 Order。)如果指定了
LIMIT
(或FETCH FIRST
)或OFFSET
子句,则SELECT
语句仅返回结果行的子集。 (请参见下面的LIMIT Clause。)如果指定了
FOR UPDATE
,FOR NO KEY UPDATE
,FOR SHARE
或FOR KEY SHARE
,则SELECT
语句将锁定所选行以防止并发更新。 (请参见下面的锁定条款。)
您必须对SELECT
命令中使用的每一列具有SELECT
特权。 FOR NO KEY UPDATE
,FOR UPDATE
,FOR SHARE
或FOR KEY SHARE
的使用也需要UPDATE
特权(对于这样选择的每个表的至少一列)。
Parameters
WITH Clause
WITH
子句允许您指定一个或多个子查询,这些查询可以通过名称在主查询中进行引用。子查询在主查询期间有效地充当临时表或视图。每个子查询可以是SELECT
,TABLE
,VALUES
,INSERT
,UPDATE
或DELETE
语句。在WITH
中编写数据修改语句(INSERT
,UPDATE
或DELETE
)时,通常包含RETURNING
子句。它是RETURNING
的输出,而不是语句所修改的基础表,形成了由主查询读取的临时表。如果省略RETURNING
,则该语句仍将执行,但不会产生任何输出,因此主查询无法将其引用为表。
必须为每个WITH
查询指定一个名称(无模式限定)。 (可选)可以指定列名列表;如果省略此选项,则从子查询中推断出列名。
如果指定了RECURSIVE
,则它允许SELECT
子查询按名称引用自身。这样的子查询必须具有以下形式
non_recursive_term UNION [ ALL | DISTINCT ] recursive_term
递归自引用必须出现在UNION
的右侧。每个查询只允许一个递归自引用。不支持递归数据修改语句,但是您可以在数据修改语句中使用递归SELECT
查询的结果。有关示例,请参见Section 7.8。
RECURSIVE
的另一个作用是不必对WITH
个查询进行排序:查询可以引用列表中后面的另一个查询。 (但是,不会实现循环引用或相互递归.)如果没有RECURSIVE
,则WITH
查询只能引用WITH
列表中较早的同级WITH
查询。
WITH
查询的一个关键属性是,即使主查询多次引用它们,一次执行主查询也只会对它们进行一次评估。特别是,无论主查询是读取全部输出还是输出任何内容,都保证数据修改语句仅执行一次。
如果WITH
子句中有多个查询,则RECURSIVE
应该只写一次,紧接在WITH
之后。尽管它对不使用递归或前向引用的查询没有影响,但它适用于WITH
子句中的所有查询。
主查询和WITH
查询都(名义上)同时执行。这意味着在WITH
中修改数据的语句的效果无法从查询的其他部分看到,除非读取其RETURNING
输出。如果两个这样的数据修改语句试图修改同一行,则结果不确定。
有关其他信息,请参见Section 7.8。
FROM Clause
FROM
子句为SELECT
指定一个或多个源表。如果指定了多个源,则结果为所有源的笛卡尔乘积(交叉联接)。但是通常会添加限定条件(通过WHERE
),以将返回的行限制为笛卡尔乘积的一小部分。
FROM
子句可以包含以下元素:
table_name
- 现有表或视图的名称(可选,由模式限定)。如果在表名之前指定了
ONLY
,则仅扫描该表。如果未指定ONLY
,则扫描该表及其所有后代表(如果有)。 (可选)可以在表名称后指定*
,以明确指示包括后代表。
- 现有表或视图的名称(可选,由模式限定)。如果在表名之前指定了
alias
- 包含别名的
FROM
项的替代名称。别名是为了简洁起见或消除自联接的歧义(多次扫描同一张表)。提供别名后,它将完全隐藏表或函数的实际名称。例如FROM foo AS f
,SELECT
的其余部分必须将此FROM
项称为f
而不是foo
。如果写入了别名,则还可以写入列别名列表以为表的一个或多个列提供替代名称。
- 包含别名的
TABLESAMPLE sampling_method ( argument [, ...] ) [ REPEATABLE ( seed ) ]
-
table_name
后的TABLESAMPLE
子句表示应使用指定的sampling_method
*检索该表中行的子集。该采样先于其他过滤器(例如WHERE
子句)的应用。标准的 PostgreSQL 发行版包括BERNOULLI
和SYSTEM
两种采样方法,并且可以通过扩展将其他采样方法安装在数据库中。
-
BERNOULLI
和SYSTEM
采样方法每个都接受一个* argument
*,这是要采样的表的分数,以 0 到 100 之间的百分比表示。此参数可以是任何real
值的表达式。 (其他采样方法可能会接受更多或不同的参数.)这两种方法各自返回表的随机选择 samples,该 samples 将包含表行的指定百分比。 BERNOULLI
方法扫描整个表,并以指定的概率独立选择或忽略单个行。 SYSTEM
方法执行块级采样,每个块具有指定的被选择机会;返回每个选定块中的所有行。当指定较小的采样百分比时,SYSTEM
方法比BERNOULLI
方法要快得多,但是由于聚类的影响,它可能返回表中的随机性较低的 samples。
可选的REPEATABLE
子句指定一个* seed
数字或表达式,用于在采样方法内生成随机数。种子值可以是任何非空浮点值。如果同时没有更改表,则两个指定相同种子和 argument
*值的查询将选择表的相同 samples。但是,不同的种子值通常会产生不同的 samples。如果未提供REPEATABLE
,则根据系统生成的种子为每个查询选择一个新的随机 samples。请注意,某些附加采样方法不接受REPEATABLE
,并且每次使用时都会产生新的 samples。
select
- 子_可以出现在
FROM
子句中。这就像在单个SELECT
命令期间将其输出创建为临时表一样。请注意,子SELECT
必须用括号括起来,并为其提供别名必须。 VALUES命令也可以在这里使用。
- 子_可以出现在
with_query_name
WITH
查询通过写入其名称来引用,就像查询的名称是表名称一样。 (实际上,WITH
查询会隐藏任何具有相同名称的真实表,以用于主查询.如有必要,您可以通过模式限定表名称来引用相同名称的真实表.)别名可以是提供方式与表格相同。
function_name
- 函数调用可以出现在
FROM
子句中。 (这对于返回结果集的函数特别有用,但是可以使用任何函数.)这就像在单个SELECT
命令期间将函数的输出创建为临时表一样。当将可选的WITH ORDINALITY
子句添加到函数调用中时,新列将追加到所有函数的输出列之后,并为每行编号。
- 函数调用可以出现在
可以使用与表相同的方式提供别名。如果编写了别名,则还可以编写列别名列表以为函数的复合返回类型的一个或多个属性提供替代名称,包括由ORDINALITY
添加的列(如果存在)。
多个函数调用可以用ROWS FROM( ... )
包围起来,从而组合成一个FROM
子句。此类项目的输出是每个函数的第一行的串联,然后是每个函数的第二行的串联,依此类推。如果某些函数产生的行少于其他函数,则将空值替换为丢失的数据,以便返回的总行数始终与产生最多行的函数相同。
如果已将函数定义为返回record
数据类型,则必须存在别名或关键字AS
,后跟格式为( column_name data_type [, ... ])
的列定义列表。列定义列表必须匹配该函数返回的实际列数和类型。
使用ROWS FROM( ... )
语法时,如果其中一个函数需要列定义列表,则最好将列定义列表放在ROWS FROM( ... )
内的函数调用之后。仅当只有一个函数且没有WITH ORDINALITY
子句时,才能将列定义列表放在ROWS FROM( ... )
构造之后。
要将ORDINALITY
与列定义列表一起使用,必须使用ROWS FROM( ... )
语法并将列定义列表放在ROWS FROM( ... )
内。
join_type
- One of
[ 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
项,为方便起见,我们将其称为“表”,尽管实际上它们可以是任何类型的FROM
项。如有必要,请使用括号确定嵌套 Sequences。在没有括号的情况下,JOIN
从左到右嵌套。无论如何,JOIN
的绑定比分隔FROM
-list 的逗号更紧密。
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
列表的简写,该列表提到两个表中具有匹配名称的所有列。如果没有公共列名,则NATURAL
等效于ON TRUE
。
LATERAL
LATERAL
关键字可以位于子SELECT
FROM
项之前。这使子SELECT
可以引用FROM
项中出现在FROM
列表中的FROM
项的列。 (如果没有LATERAL
,则每个子SELECT
都会独立评估,因此不能交叉引用任何其他FROM
项.)
LATERAL
也可以在函数调用FROM
项之前,但是在这种情况下,它是一个干扰词,因为函数表达式在任何情况下都可以引用较早的FROM
项。
LATERAL
项可以出现在FROM
列表的顶级或JOIN
树中。在后一种情况下,它也可以引用位于JOIN
左侧的任何项目。
当FROM
项包含LATERAL
交叉引用时,评估将按以下步骤进行:对于提供交叉引用列的FROM
项的每一行,或提供该列的多个FROM
项的行集,将使用LATERAL
项进行评估该行或行集的列值。像往常一样,将结果行与从中计算出的行连接在一起。对列源表中的每一行或每一行行重复此操作。
列源表必须与LATERAL
项连接成INNER
或LEFT
,否则将没有定义明确的行集可从其中计算LATERAL
项的每组行。因此,尽管诸如X RIGHT JOIN LATERAL Y
之类的构造在语法上是有效的,但实际上不允许* Y
引用 X
*。
WHERE Clause
可选的WHERE
子句具有常规形式
WHERE condition
其中* condition
*是计算结果为boolean
类型的任何表达式。任何不满足此条件的行将从输出中删除。如果用实际的行值代替任何变量引用,如果该行返回 true,则满足该条件。
GROUP BY 条款
可选的GROUP BY
子句具有常规形式
GROUP BY grouping_element [, ...]
GROUP BY
将所有共享相同表达式的分组表达式的所有选定行压缩为单行。在grouping_element
内部使用的expression
可以是 Importing 列名称,也可以是输出列的名称或序号(SELECT
列表项),也可以是由 Importing 列值形成的任意表达式。如有歧义,GROUP BY
名称将被解释为 Importing 列名称,而不是输出列名称。
如果GROUPING SETS
,ROLLUP
或CUBE
中的任何一个作为分组元素存在,则GROUP BY
子句总体上定义了一些独立的* grouping sets
*。这样的效果等效于在子查询之间构造UNION ALL
,并将各个分组集作为其GROUP BY
子句。有关处理分组集的更多详细信息,请参见Section 7.2.4。
汇总函数(如果有的话)在组成每个组的所有行中进行计算,从而为每个组生成单独的值。 (如果有聚合函数但没有GROUP BY
子句,则该查询被视为具有包含所有选定行的单个组.)可以通过在聚合函数调用上附加FILTER
子句来进一步过滤馈给每个聚合函数的行集。 ;有关更多信息,请参见Section 4.2.7。当存在FILTER
子句时,只有与之匹配的那些行才包含在该聚合函数的 Importing 中。
当存在GROUP BY
或存在任何聚合函数时,除非聚合函数内或当非分组列在功能上取决于分组列时,否则SELECT
列表表达式引用未分组列是无效的,因为否则对于未分组的列返回一个可能的值。如果分组的列(或其子集)是包含未分组的列的表的主键,则存在功能依赖性。
请记住,在评估HAVING
子句或SELECT
列表中的任何“标量”表达式之前,必须先评估所有聚合函数。这意味着,例如CASE
表达式不能用于跳过对聚合函数的求值;参见Section 4.2.14。
当前,无法用GROUP BY
指定FOR NO KEY UPDATE
,FOR UPDATE
,FOR SHARE
和FOR KEY SHARE
。
HAVING Clause
可选的HAVING
子句具有常规形式
HAVING condition
其中* condition
*与为WHERE
子句指定的相同。
HAVING
消除不满足条件的组行。 HAVING
与WHERE
不同:WHERE
在应用GROUP BY
之前过滤单个行,而HAVING
过滤由GROUP BY
创建的组行。 * condition
*中引用的每个列都必须明确引用一个分组列,除非该引用出现在聚合函数内或未分组的列在功能上取决于分组列。
即使没有GROUP BY
子句,HAVING
的存在也会将查询转换为分组查询。这与查询包含聚合函数但不包含GROUP BY
子句时发生的情况相同。所有选定的行都被视为形成一个单一的组,并且SELECT
列表和HAVING
子句只能引用聚合函数中的表列。如果HAVING
条件为 true,则此查询将发出单行,如果HAVING
条件为 true,则将发出零行。
当前,无法用HAVING
指定FOR NO KEY UPDATE
,FOR UPDATE
,FOR SHARE
和FOR KEY SHARE
。
WINDOW Clause
可选的WINDOW
子句具有常规形式
WINDOW window_name AS ( window_definition ) [, ...]
其中* window_name
是可以从OVER
子句或后续窗口定义中引用的名称,而 window_definition
*是
[ existing_window_name ]
[ PARTITION BY expression [, ...] ]
[ ORDER BY expression [ ASC | DESC | USING operator ] [ NULLS { FIRST | LAST } ] [, ...] ]
[ frame_clause ]
如果指定了* existing_window_name
*,则必须引用WINDOW
列表中的较早条目;新窗口将复制该条目的分区子句以及其排序子句(如果有)。在这种情况下,新窗口无法指定自己的PARTITION BY
子句,并且只有在复制的窗口没有一个子句的情况下,它才能指定ORDER BY
。新窗口始终使用其自己的 frame 子句;复制的窗口不得指定 frame 子句。
PARTITION BY
列表的元素的解释方式与按条款分组的元素几乎相同,不同之处在于它们始终是简单表达式,而不是输出列的名称或编号。另一个区别是这些表达式可以包含聚合函数调用,这在常规GROUP BY
子句中是不允许的。在此处允许使用它们,因为窗口在分组和聚合之后发生。
类似地,ORDER BY
列表的元素的解释方式与按条款 Order的元素几乎相同,不同之处在于,表达式始终被视为简单表达式,而不是输出列的名称或编号。
可选的* frame_clause
为依赖于框架的窗口功能定义“窗口框架”(并非全部)。窗口框架是查询的每一行(称为当前行*)的一组相关行。 * frame_clause
*可以是以下之一
{ RANGE | ROWS } frame_start
{ RANGE | ROWS } BETWEEN frame_start AND frame_end
其中* frame_start
和 frame_end
*可以是以下之一
UNBOUNDED PRECEDING
value PRECEDING
CURRENT ROW
value FOLLOWING
UNBOUNDED FOLLOWING
如果省略* frame_end
,则默认为CURRENT ROW
。限制条件是 frame_start
不能为UNBOUNDED FOLLOWING
, frame_end
不能为UNBOUNDED PRECEDING
,并且 frame_end
选择不能在以上列表中早于 frame_start
*选择出现-例如,不允许RANGE BETWEEN CURRENT ROW AND value PRECEDING
。
默认的取景选项为RANGE UNBOUNDED PRECEDING
,与RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
相同;它将帧设置为从分区开始到当前行的最后一个对等方的所有行(ORDER BY
认为与当前行等效的行,如果没有ORDER BY
则为所有行)。通常,UNBOUNDED PRECEDING
表示帧以分区的第一行开始,类似地,UNBOUNDED FOLLOWING
表示帧以分区的最后一行结束(无论RANGE
或ROWS
模式如何)。在ROWS
模式下,CURRENT ROW
表示帧从当前行开始或结束;但在RANGE
模式下,则表示帧以ORDER BY
Sequences 中当前行的第一个或最后一个对等点开始或结束。目前仅在ROWS
模式下允许* value
* PRECEDING
和* value
* FOLLOWING
情况。它们指示帧以当前行之前或之后许多行的行开始或结束。 * value
*必须是不包含任何变量,聚合函数或窗口函数的整数表达式。该值不能为 null 或负数;但它可以为零,从而选择当前行本身。
请注意,如果ORDER BY
排序不是唯一地对行进行排序,则ROWS
选项可能会产生不可预测的结果。 RANGE
选项旨在确保按ORDER BY
Sequences 对等的行被相同地对待。所有对等行将在同一帧中。
WINDOW
子句的目的是指定出现在查询SELECT List或按条款 Order中的窗口功能的行为。这些函数可以在其OVER
子句中按名称引用WINDOW
子句条目。但是,不必在任何地方引用WINDOW
子句条目。如果查询中未使用它,则将其忽略。可以根本不使用任何WINDOW
子句来使用窗口函数,因为窗口函数调用可以直接在其OVER
子句中指定其窗口定义。但是,当多个窗口函数需要相同的窗口定义时,WINDOW
子句可以节省键入内容。
当前,无法用WINDOW
指定FOR NO KEY UPDATE
,FOR UPDATE
,FOR SHARE
和FOR KEY SHARE
。
Section 3.5,Section 4.2.8和Section 7.2.5中详细描述了窗口功能。
SELECT List
SELECT
列表(在关键字SELECT
和FROM
之间)指定了构成SELECT
语句的输出行的表达式。表达式可以(通常)引用FROM
子句中计算的列。
就像在表中一样,SELECT
的每个输出列都有一个名称。在简单的SELECT
中,此名称仅用于标记要显示的列,但是当SELECT
是较大查询的子查询时,该名称在较大查询中被视为由该子查询生成的虚拟表的列名。 -查询。要指定用于输出列的名称,请在该列的表达式后 ImportingAS
* output_name
*。 (您可以省略AS
,但仅在所需的输出名称与任何 PostgreSQL 关键字不匹配时(请参见Appendix C)。为了防止将来可能再添加关键字,建议始终将AS
或双引号引起来。)如果您未指定列名,则 PostgreSQL 将自动选择一个名称。如果列的表达式是简单的列引用,则所选名称与该列的名称相同。在更复杂的情况下,可以使用函数或类型名称,或者系统可以使用生成的名称(例如?column?
)。
输出列的名称可用于在ORDER BY
和GROUP BY
子句中引用该列的值,但不能在WHERE
或HAVING
子句中引用;在那里,您必须写出表达式。
代替表达式,*
可以作为所选行的所有列的速记形式写在输出列表中。另外,您可以写table_name.*
作为该表的列的简写。在这些情况下,无法使用AS
指定新名称;输出列名称将与表列名称相同。
根据 SQL 标准,应在应用DISTINCT
,ORDER BY
或LIMIT
之前计算输出列表中的表达式。当使用DISTINCT
时,这显然是必要的,因为否则不清楚将哪些值区分。但是,在许多情况下,如果在ORDER BY
和LIMIT
之后计算输出表达式是很方便的;特别是在输出列表包含任何易失性或昂贵函数的情况下。通过这种行为,函数求值的 Sequences 更加直观,并且不会有与从不出现在输出中的行相对应的求值。 PostgreSQL 将在排序和限制之后有效地评估输出表达式,只要DISTINCT
,ORDER BY
或GROUP BY
中未引用这些表达式即可。 (作为反例,SELECT f(x) FROM tab ORDER BY 1
显然必须在排序之前对f(x)
进行求值.)包含有 set-returning 函数的输出表达式在排序之后和限制之前都会得到有效求值,因此LIMIT
会切断来自 set-returning 函数的输出。
Note
9.6 之前的 PostgreSQL 版本没有提供关于输出表达式求值与排序和限制的时间的任何保证;它取决于所选查询计划的形式。
DISTINCT Clause
如果指定了SELECT DISTINCT
,则会从结果集中删除所有重复的行(每组重复项中保留一行)。 SELECT ALL
表示相反的情况:所有行都保留;这是默认值。
SELECT DISTINCT ON ( expression [, ...] )
仅保留给定表达式等于的每组行的第一行。使用与ORDER BY
相同的规则来解释DISTINCT ON
表达式(请参见上文)。请注意,除非使用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
组中所需的行优先级。
当前,无法用DISTINCT
指定FOR NO KEY UPDATE
,FOR UPDATE
,FOR SHARE
和FOR KEY SHARE
。
UNION Clause
UNION
子句具有以下一般形式:
select_statement UNION [ ALL | DISTINCT ] select_statement
select_statement
*是任何没有ORDER BY
,LIMIT
,FOR NO KEY UPDATE
,FOR UPDATE
,FOR SHARE
或FOR KEY SHARE
子句的SELECT
语句。 (如果将ORDER BY
和LIMIT
括在括号中,则可以将其附加到子表达式.不带括号的话,这些子句将应用于UNION
的结果,而不是其右侧 Importing 表达式.)
UNION
运算符计算所涉及的SELECT
语句返回的行的集合并集。如果行出现在至少一个结果集中,则该行位于两个结果集中的集合并集中。表示UNION
的直接操作数的两个SELECT
语句必须产生相同数量的列,并且对应的列必须具有兼容的数据类型。
除非指定了ALL
选项,否则UNION
的结果不包含任何重复的行。 ALL
防止重复项的消除。 (因此,UNION ALL
通常比UNION
快得多;可以使用ALL
.)可以编写DISTINCT
来明确指定消除重复行的默认行为。
除非括号中另有说明,否则同一SELECT
语句中的多个UNION
运算符从左到右求值。
当前,不能为UNION
结果或UNION
的任何 Importing 指定FOR NO KEY UPDATE
,FOR UPDATE
,FOR SHARE
和FOR KEY SHARE
。
INTERSECT Clause
INTERSECT
子句具有以下一般形式:
select_statement INTERSECT [ ALL | DISTINCT ] select_statement
select_statement
*是任何没有ORDER BY
,LIMIT
,FOR NO KEY UPDATE
,FOR UPDATE
,FOR SHARE
或FOR KEY SHARE
子句的SELECT
语句。
INTERSECT
运算符计算所涉及的SELECT
语句返回的行的集合交集。如果一行出现在两个结果集中,则该行位于两个结果集中的交集。
除非指定了ALL
选项,否则INTERSECT
的结果不包含任何重复的行。使用ALL
,在左表中具有* m
重复项和在右表中具有 n
重复项的行将在结果集中出现 min( m
, n
*)次。可以编写DISTINCT
来明确指定消除重复行的默认行为。
除非括号中另有规定,否则在同一SELECT
语句中的多个INTERSECT
运算符从左到右求值。 INTERSECT
的绑定比UNION
的绑定更紧密。也就是说,A UNION B INTERSECT C
将被读取为A UNION (B INTERSECT C)
。
当前,不能为INTERSECT
结果或INTERSECT
的任何 Importing 指定FOR NO KEY UPDATE
,FOR UPDATE
,FOR SHARE
和FOR KEY SHARE
。
EXCEPT Clause
EXCEPT
子句具有以下一般形式:
select_statement EXCEPT [ ALL | DISTINCT ] select_statement
select_statement
*是任何没有ORDER BY
,LIMIT
,FOR NO KEY UPDATE
,FOR UPDATE
,FOR SHARE
或FOR KEY SHARE
子句的SELECT
语句。
EXCEPT
运算符将计算左SELECT
语句的结果中的行集,而不计算右右语句的结果。
除非指定了ALL
选项,否则EXCEPT
的结果不包含任何重复的行。使用ALL
,在左表中具有* m
重复项并且在右表中具有 n
重复项的行将在结果集中出现 max( m
- n
*,0)次。可以编写DISTINCT
来明确指定消除重复行的默认行为。
除非括号中另有规定,否则在同一SELECT
语句中的多个EXCEPT
运算符从左到右求值。 EXCEPT
的绑定级别与UNION
相同。
当前,不能为EXCEPT
结果或EXCEPT
的任何 Importing 指定FOR NO KEY UPDATE
,FOR UPDATE
,FOR SHARE
和FOR KEY SHARE
。
ORDER BY 条款
可选的ORDER BY
子句具有以下一般形式:
ORDER BY expression [ ASC | DESC | USING operator ] [ NULLS { FIRST | LAST } ] [, ...]
ORDER BY
子句使结果行根据指定的表达式排序。如果根据最左边的表达式两行相等,则根据下一个表达式对它们进行比较,依此类推。如果根据所有指定的表达式它们相等,则将根据实现的 Sequences 返回它们。
每个* expression
*可以是输出列(SELECT
列表项)的名称或序号,也可以是由 Importing 列值组成的任意表达式。
序号是指输出列的序数位置(从左到右)。通过此功能,可以基于没有唯一名称的列来定义 Sequences。这绝对不是绝对必要的,因为始终可以使用AS
子句为输出列分配名称。
也可以在ORDER BY
子句中使用任意表达式,包括不出现在SELECT
输出列表中的列。因此,以下语句是有效的:
SELECT name FROM distributors ORDER BY code;
此功能的局限性在于,应用于UNION
,INTERSECT
或EXCEPT
子句结果的ORDER BY
子句只能指定输出列名称或数字,而不能指定表达式。
如果ORDER BY
表达式是与输出列名和 Importing 列名都匹配的简单名称,则ORDER BY
会将其解释为输出列名。这与GROUP BY
在相同情况下所做的选择相反。使该不一致与 SQL 标准兼容。
可以选择在ORDER BY
子句中的任何表达式之后添加关键字ASC
(升序)或DESC
(降序)。如果未指定,则默认为ASC
。或者,可以在USING
子句中指定特定的排序运算符名称。Order 运算符必须是小于或大于某些 B 树运算符系列的成员。 ASC
通常等效于USING <
,而DESC
通常等效于USING >
。 (但是,用户定义的数据类型的创建者可以准确定义默认的排序 Sequences,并且它可能与其他名称的运算符相对应.)
如果指定了NULLS LAST
,则空值将在所有非空值之后排序;如果指定了NULLS FIRST
,则空值将在所有非空值之前排序。如果两者均未指定,则默认行为是NULLS LAST
(当指定或隐含ASC
时)和NULLS FIRST
(当指定或隐含DESC
时)(因此,默认值的作用是空值大于非空值)。指定USING
时,默认的空值排序取决于运算符是小于运算符还是大于运算符。
注意,排序选项仅适用于它们遵循的表达式。例如ORDER BY x, y DESC
与ORDER BY x DESC, y DESC
的含义不同。
字符串数据是根据应用于要排序的列的排序规则进行排序的。可以通过在* expression
*中包含COLLATE
子句(例如ORDER BY mycolumn COLLATE "en_US"
)来覆盖该值。有关更多信息,请参见Section 4.2.10和Section 23.2。
LIMIT Clause
LIMIT
子句包含两个独立的子句:
LIMIT { count | ALL }
OFFSET start
count
指定要返回的最大行数,而start
指定要开始返回的行之前要跳过的行数。如果同时指定了两者,则在开始对要返回的count
行进行计数之前,将跳过start
*行。
如果* count
表达式的结果为 NULL,则将其视为LIMIT ALL
,即无限制。如果 start
*评估为 NULL,则将其与OFFSET 0
相同。
SQL:2008 引入了不同的语法来实现相同的结果,PostgreSQL 也支持该语法。它是:
OFFSET start { ROW | ROWS }
FETCH { FIRST | NEXT } [ count ] { ROW | ROWS } ONLY
在这种语法中,标准要求* start
或 count
值为 Literals 常量,参数或变量名;作为 PostgreSQL 扩展,允许使用其他表达式,但通常需要将其括在括号中以避免歧义。如果在FETCH
子句中省略 count
*,则默认值为 1.ROW
和ROWS
以及FIRST
和NEXT
是不影响这些子句效果的干扰词。根据标准,如果同时存在OFFSET
子句,则必须在FETCH
子句之前;但是 PostgreSQL 比较宽松,并且可以使用任何 Sequences。
使用LIMIT
时,最好使用ORDER BY
子句将结果行约束为唯一 Sequences。否则,您将获得查询行的不可预测的子集-您可能会要求 Importing 第十到第二十行,但是要求的 Sequences 是第十到第二十行?除非您指定ORDER BY
,否则您不知道该如何排序。
查询计划程序在生成查询计划时会考虑LIMIT
,因此根据LIMIT
和OFFSET
的用途,您很可能会获得不同的计划(产生不同的行 Sequences)。因此,除非使用ORDER BY
强制执行可预测的结果排序,否则使用不同的LIMIT
/OFFSET
值来选择查询结果的不同子集会得出不一致的结果。这不是错误;除非使用ORDER BY
约束该 Sequences,否则 SQL 不会保证以任何特定 Sequences 传递查询结果,这是一个固有的结果。
如果没有ORDER BY
来强制执行确定性子集的选择,则甚至可以重复执行同一LIMIT
查询以返回表行的不同子集。再次,这不是错误;在这种情况下,不能保证结果的确定性。
锁定条款
FOR UPDATE
,FOR NO KEY UPDATE
,FOR SHARE
和FOR KEY SHARE
是锁定子句;它们会影响SELECT
锁定从表中获取的行的方式。
锁定子句具有一般形式
FOR lock_strength [ OF table_name [, ...] ] [ NOWAIT | SKIP LOCKED ]
lock_strength
*可以是以下其中一个
UPDATE
NO KEY UPDATE
SHARE
KEY SHARE
有关每种行级锁定模式的更多信息,请参考Section 13.3.2。
为防止该操作 await 其他事务提交,请使用NOWAIT
或SKIP LOCKED
选项。使用NOWAIT
,如果不能立即锁定选定的行,则该语句报告错误,而不是 await。使用SKIP LOCKED
,将跳过所有不能立即锁定的选定行。跳过锁定的行会提供不一致的数据视图,因此这不适用于一般用途的工作,但可用于避免多个使用者访问类似队列的表时发生的锁争用。请注意,NOWAIT
和SKIP LOCKED
仅适用于行级锁-所需的ROW SHARE
表级锁仍以常规方式获取(请参见Chapter 13)。如果需要不 await 就获取表级锁,则可以先将LOCK与NOWAIT
选项一起使用。
如果在锁定子句中指定了特定的表,则仅锁定那些表中的行;照常读取SELECT
中使用的任何其他表。没有表列表的锁定子句会影响该语句中使用的所有表。如果将锁定子句应用于视图或子查询,则它将影响该视图或子查询中使用的所有表。但是,这些子句不适用于主要查询引用的WITH
查询。如果希望在WITH
查询中发生行锁定,请在WITH
查询中指定锁定子句。
如果有必要为不同的表指定不同的锁定行为,则可以编写多个锁定子句。如果同一表被多个锁定子句提及(或隐式影响),则将其视为仅由最强的子表指定。同样,如果在影响表的任何子句中指定了表,则表将被处理为NOWAIT
。否则,如果在影响它的任何子句中指定了该参数,它将被处理为SKIP LOCKED
。
在无法用单独的表行清楚地标识返回的行的上下文中,不能使用锁定子句;例如,它们不能与聚合一起使用。
当锁定子句出现在SELECT
查询的顶层时,锁定的行与查询返回的行完全相同。对于联接查询,锁定的行是那些有助于返回联接行的行。另外,满足查询条件的行将自查询快照起被锁定,尽管如果在快照后对其进行更新并且不再满足查询条件,则不会返回这些行。如果使用LIMIT
,一旦返回了足够的行以满足限制,锁定就会停止(但请注意,被OFFSET
跳过的行将被锁定)。同样,如果在游标的查询中使用了锁定子句,则仅锁定实际被游标读取或跳过的行。
当子句SELECT
中出现锁定子句时,锁定的行是子查询返回给外部查询的行。这可能涉及比仅检查子查询建议的行少的行,因为来自外部查询的条件可能用于优化子查询的执行。例如,
SELECT * FROM (SELECT * FROM mytable FOR UPDATE) ss WHERE col1 = 5;
将仅锁定具有col1 = 5
的行,即使该条件在文本上不在子查询中。
以前的版本无法保留由以后的保存点升级的锁。例如,此代码:
BEGIN;
SELECT * FROM mytable WHERE key = 1 FOR UPDATE;
SAVEPOINT s;
UPDATE mytable SET ... WHERE key = 1;
ROLLBACK TO s;
将无法在ROLLBACK TO
之后保留FOR UPDATE
锁定。此问题已在 9.3 版中修复。
Caution
在READ COMMITTED
事务隔离级别运行并使用ORDER BY
和锁定子句的SELECT
命令有可能返回无序的行。这是因为先应用ORDER BY
。该命令对结果进行排序,但随后可能会阻止尝试获得对一个或多个行的锁定。一旦SELECT
解除阻止,某些排序列的值可能已被修改,从而导致这些行似乎是乱序的(尽管就原始列值而言,它们是有序的)。可以通过在子查询中放置FOR UPDATE/SHARE
子句来解决此问题,例如
SELECT * FROM (SELECT * FROM mytable FOR UPDATE) ss ORDER BY column1;
请注意,这将导致锁定mytable
的所有行,而位于顶层的FOR UPDATE
将仅锁定实际返回的行。这可能会导致明显的性能差异,特别是如果ORDER BY
与LIMIT
或其他限制结合使用时。因此,仅当期望并发更新排序列并且需要严格排序的结果时,才建议使用此技术。
在REPEATABLE READ
或SERIALIZABLE
事务隔离级别,这将导致序列化失败(SQLSTATE
为'40001'
),因此在这些隔离级别下不可能接收乱序的行。
TABLE Command
The command
TABLE name
相当于
SELECT * FROM name
在部分复杂查询中,它可用作顶级命令或节省空间的语法变体。 TABLE
只能使用WITH
,UNION
,INTERSECT
,EXCEPT
,ORDER BY
,LIMIT
,OFFSET
,FETCH
和FOR
锁定子句;不能使用WHERE
子句和任何形式的聚合。
Examples
要将表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 * FROM unnest(ARRAY['a','b','c','d','e','f']) WITH ORDINALITY;
unnest | ordinality
--------+----------
a | 1
b | 2
c | 3
d | 4
e | 5
f | 6
(6 rows)
本示例说明如何使用简单的WITH
子句:
WITH t AS (
SELECT random() as x FROM generate_series(1, 3)
)
SELECT * FROM t
UNION ALL
SELECT * FROM t
x
--------------------
0.534150459803641
0.520092216785997
0.0735620250925422
0.534150459803641
0.520092216785997
0.0735620250925422
请注意,WITH
查询仅被评估一次,因此我们得到了两个具有相同三个随机值的集合。
本示例使用WITH RECURSIVE
从仅显示直接下属的表中查找员工 Mary 的所有下属(直接或间接)及其间接程度:
WITH RECURSIVE employee_recursive(distance, employee_name, manager_name) AS (
SELECT 1, employee_name, manager_name
FROM employee
WHERE manager_name = 'Mary'
UNION ALL
SELECT er.distance + 1, e.employee_name, e.manager_name
FROM employee_recursive er, employee e
WHERE er.employee_name = e.manager_name
)
SELECT distance, employee_name FROM employee_recursive;
请注意递归查询的典型形式:初始条件,后跟UNION
,后跟查询的递归部分。确保查询的递归部分最终不会返回任何 Tuples,否则查询将无限期地循环。 (有关更多示例,请参见Section 7.8。)
本示例使用LATERAL
为manufacturers
表的每一行应用返回集合的函数get_product_names()
:
SELECT m.name AS mname, pname
FROM manufacturers m, LATERAL get_product_names(m.id) pname;
当前没有任何产品的制造商不会出现在结果中,因为它是内部联接。如果我们希望在结果中包括此类制造商的名称,则可以执行以下操作:
SELECT m.name AS mname, pname
FROM manufacturers m LEFT JOIN LATERAL get_product_names(m.id) pname ON true;
Compatibility
当然,SELECT
语句与 SQL 标准兼容。但是有一些扩展和缺少的功能。
省略了 FROM 子句
PostgreSQL 允许省略FROM
子句。它可以直接用于计算简单表达式的结果:
SELECT 2+2;
?column?
----------
4
其他一些 SQL 数据库无法做到这一点,除非引入一个虚拟的单行表来执行SELECT
。
请注意,如果未指定FROM
子句,则查询无法引用任何数据库表。例如,以下查询无效:
SELECT distributors.* WHERE distributors.name = 'Westward';
PostgreSQL 在 8.1 之前的版本将接受这种形式的查询,并为查询所引用的每个表在查询的FROM
子句中添加一个隐式条目。不再允许这样做。
空的 SELECT 列表
SELECT
之后的输出表达式列表可以为空,从而生成零列结果表。根据 SQL 标准,这是无效的语法。 PostgreSQL 允许它与允许零列表保持一致。但是,使用DISTINCT
时不允许使用空列表。
省略 AS 关键字
在 SQL 标准中,只要新列名是有效的列名(即与任何保留关键字不同),就可以在输出列名之前省略可选关键字AS
。 PostgreSQL 的限制更严格:如果新的列名称完全匹配任何关键字(保留或不保留),则需要AS
。推荐的做法是使用AS
或双引号输出列名,以防止与将来添加关键字的任何可能的冲突。
在FROM
项中,标准和 PostgreSQL 都允许在作为未保留关键字的别名之前省略AS
。但是由于语法上的歧义,这对于输出列名称是不切实际的。
仅与继承
在编写ONLY
时(例如SELECT * FROM ONLY (tab1), ONLY (tab2) WHERE ...
),SQL 标准要求在表名前后加上括号。 PostgreSQL 认为这些括号是可选的。
PostgreSQL 允许写入尾随*
以显式指定包括子表在内的非ONLY
行为。该标准不允许这样做。
(这些要点同样适用于所有支持ONLY
选项的 SQL 命令.)
TABLESAMPLE 子句限制
当前仅在常规表和实例化视图上接受TABLESAMPLE
子句。根据 SQL 标准,应该可以将其应用于任何FROM
项。
来自 FROM 的函数调用
PostgreSQL 允许将函数调用直接编写为FROM
列表的成员。在 SQL 标准中,有必要将此类函数调用包装在 sub_SELECT
中。也就是说,语法FROM func(...) alias
大约等于FROM LATERAL (SELECT func(...)) alias
。注意LATERAL
被认为是隐式的;这是因为该标准要求FROM
中的UNNEST()
项具有LATERAL
语义。 PostgreSQL 与其他返回集合的函数一样对待UNNEST()
。
命名空间可用于 GROUP BY 和 ORDER BY
在 SQL-92 标准中,ORDER BY
子句只能使用输出列名称或数字,而GROUP BY
子句只能使用基于 Importing 列名称的表达式。 PostgreSQL 扩展了每个子句以允许其他选择(但是如果有歧义,它会使用标准的解释)。 PostgreSQL 还允许两个子句都指定任意表达式。请注意,出现在表达式中的名称将始终被视为 Importing 列名称,而不是输出列名称。
SQL:1999 和更高版本使用略有不同的定义,该定义并不完全向上兼容 SQL-92.但是,在大多数情况下,PostgreSQL 将以与 SQL:1999 相同的方式解释ORDER BY
或GROUP BY
表达式。
Functional Dependencies
PostgreSQL 仅在表的主键包含在GROUP BY
列表中时才识别功能依赖性(允许从GROUP BY
省略列)。 SQL 标准指定了应识别的其他条件。
WINDOW 子句限制
SQL 标准为窗口* frame_clause
*提供了其他选项。 PostgreSQL 当前仅支持上面列出的选项。
LIMIT 和 OFFSET
子句LIMIT
和OFFSET
是 PostgreSQL 特定的语法,也由 MySQL 使用。 SQL:2008 标准引入了具有相同功能的子句OFFSET ... FETCH {FIRST|NEXT} ...
,如上面的LIMIT Clause所示。 IBM DB2 也使用此语法。 (为 Oracle 编写的应用程序经常使用一种变通办法来实现这些子句的效果,该变通办法涉及自动生成的rownum
列(在 PostgreSQL 中不可用)。
FOR NO KEY UPDATE,FOR UPDATE,FOR SHARE,FOR KEY SHARE
尽管FOR UPDATE
出现在 SQL 标准中,但该标准仅允许将其作为DECLARE CURSOR
的选项。 PostgreSQL 允许它在任何SELECT
查询以及 subSELECT
中使用,但这是一个扩展。 FOR NO KEY UPDATE
,FOR SHARE
和FOR KEY SHARE
变体以及NOWAIT
和SKIP LOCKED
选项未出现在标准中。
WITH 中的数据修改语句
PostgreSQL 允许INSERT
,UPDATE
和DELETE
用作WITH
查询。在 SQL 标准中找不到。
Nonstandard Clauses
DISTINCT ON ( ... )
是 SQL 标准的扩展。
ROWS FROM( ... )
是 SQL 标准的扩展。