Postgresql 中文操作指南

4.2. Value Expressions #

值表达式用在各种上下文中,例如 SELECT 命令的目标列表中、INSERTUPDATE 中的新列值中,或许多命令中的搜索条件中。值表达式的结果有时被称为 scalar, 以将其与表表达式(这是一个表)的结果区分开来。因此,值表达式也称为 scalar expressions (甚至简称 expressions)。此表达式语法允许使用算术、逻辑、集合和其他运算从基本部分计算值。

Value expressions are used in a variety of contexts, such as in the target list of the SELECT command, as new column values in INSERT or UPDATE, or in search conditions in a number of commands. The result of a value expression is sometimes called a scalar, to distinguish it from the result of a table expression (which is a table). Value expressions are therefore also called scalar expressions (or even simply expressions). The expression syntax allows the calculation of values from primitive parts using arithmetic, logical, set, and other operations.

值表达式为以下之一:

A value expression is one of the following:

除了此列表之外,还有许多构件可以归类为表达式,但并不遵循任何通用语法规则。这些通常具有函数或运算符的语义,并在 Chapter 9中的适当位置进行了解释。一个示例是 _IS NULL_子句。

In addition to this list, there are a number of constructs that can be classified as an expression but do not follow any general syntax rules. These generally have the semantics of a function or operator and are explained in the appropriate location in Chapter 9. An example is the IS NULL clause.

我们在 Section 4.1.2中已经讨论了常量。以下部分讨论其余选项。

We have already discussed constants in Section 4.1.2. The following sections discuss the remaining options.

4.2.1. Column References #

可以以下列形式引用列:

A column can be referenced in the form:

correlation.columnname

_correlation_是表名(可能包含架构名限定),或者是通过 _FROM_子句定义的表的别名。如果列名在当前查询中使用的所有表中唯一,则可以省略关联名称和分隔点。(另请参阅 Chapter 7)。

correlation is the name of a table (possibly qualified with a schema name), or an alias for a table defined by means of a FROM clause. The correlation name and separating dot can be omitted if the column name is unique across all the tables being used in the current query. (See also Chapter 7.)

4.2.2. Positional Parameters #

位置参数引用用于指示外部提供给 SQL 语句的值。参数用于 SQL 函数定义和准备的查询。一些客户端库还支持与 SQL 命令字符串分开指定数据值,在这种情况下,参数用于引用行外数据值。参数引用的形式为:

A positional parameter reference is used to indicate a value that is supplied externally to an SQL statement. Parameters are used in SQL function definitions and in prepared queries. Some client libraries also support specifying data values separately from the SQL command string, in which case parameters are used to refer to the out-of-line data values. The form of a parameter reference is:

$number

例如,考虑如下函数的定义,dept,为:

For example, consider the definition of a function, dept, as:

CREATE FUNCTION dept(text) RETURNS dept
    AS $$ SELECT * FROM dept WHERE name = $1 $$
    LANGUAGE SQL;

这里 $1 在函数被调用时引用第一个函数参数的值。

Here the $1 references the value of the first function argument whenever the function is invoked.

4.2.3. Subscripts #

如果表达式生成数组类型的值,可通过编写提取数组值中某特定元素

If an expression yields a value of an array type, then a specific element of the array value can be extracted by writing

expression[subscript]

或者通过编写提取多个相邻元素(“数组切片”)

or multiple adjacent elements (an “array slice”) can be extracted by writing

expression[lower_subscript:upper_subscript]

(此处,方括号 _[ ]_表示按字面意思显示)。每个 _subscript_本身都是一个表达式,将被四舍五入到最接近的整数值。

(Here, the brackets [ ] are meant to appear literally.) Each subscript is itself an expression, which will be rounded to the nearest integer value.

一般来说,数组 expression 必须用括号括起来,但是当要标引的表达式只是列引用或位置参数时,可以省略括号。此外,当原始数组是多维数组时,可以联接多个下标。例如:

In general the array expression must be parenthesized, but the parentheses can be omitted when the expression to be subscripted is just a column reference or positional parameter. Also, multiple subscripts can be concatenated when the original array is multidimensional. For example:

mytable.arraycolumn[4]
mytable.two_d_column[17][34]
$1[10:42]
(arrayfunction(a,b))[42]

最后一个示例中的括号是必需的。有关数组的更多信息,请参阅 Section 8.15

The parentheses in the last example are required. See Section 8.15 for more about arrays.

4.2.4. Field Selection #

如果表达式生成复合类型的值(行类型),可通过编写提取行中的特定字段

If an expression yields a value of a composite type (row type), then a specific field of the row can be extracted by writing

expression.fieldname

一般来说,行 expression 必须用括号括起来,但是当要从中选择表达只是表引用或位置参数时,可以省略括号。例如:

In general the row expression must be parenthesized, but the parentheses can be omitted when the expression to be selected from is just a table reference or positional parameter. For example:

mytable.mycolumn
$1.somecolumn
(rowfunction(a,b)).col3

(因此,限定列引用实际上只是字段选择语法的一个特殊情况。)一个重要的特殊情况是从复合类型(行类型)的表列中提取字段:

(Thus, a qualified column reference is actually just a special case of the field selection syntax.) An important special case is extracting a field from a table column that is of a composite type:

(compositecol).somefield
(mytable.compositecol).somefield

这里需要括号是为了表明 compositecol 是列名而不是表名,或者 mytable 是表名而不是第二种情况下的模式名。

The parentheses are required here to show that compositecol is a column name not a table name, or that mytable is a table name not a schema name in the second case.

可以通过编写 .* 来询问复合值的全部字段:

You can ask for all fields of a composite value by writing .*:

(compositecol).*

此符号的行为根据上下文而有所不同;有关详细信息,请参阅 Section 8.16.5

This notation behaves differently depending on context; see Section 8.16.5 for details.

4.2.5. Operator Invocations #

对于操作符调用,有两种可能的语法:

There are two possible syntaxes for an operator invocation:

其中 operator_标记遵循 Section 4.1.3的语法规则,或者是关键字 _AND、 _OR_和 _NOT_之一,或者是以以下形式存在的限定运算符名称:

where the operator token follows the syntax rules of Section 4.1.3, or is one of the key words AND, OR, and NOT, or is a qualified operator name in the form:

OPERATOR(schema.operatorname)

存在哪些特定运算符,以及它们是单目运算符还是二目运算符取决于系统或用户定义了哪些运算符。 Chapter 9描述了内置运算符。

Which particular operators exist and whether they are unary or binary depends on what operators have been defined by the system or the user. Chapter 9 describes the built-in operators.

4.2.6. Function Calls #

函数调用的语法是函数的名称(可以使用模式名限定),后跟用圆括号括起来的其参数列表:

The syntax for a function call is the name of a function (possibly qualified with a schema name), followed by its argument list enclosed in parentheses:

function_name ([expression [, expression ... ]] )

例如,下面计算了 2 的平方根:

For example, the following computes the square root of 2:

sqrt(2)

内置函数的列表位于 Chapter 9中。用户可以添加其他函数。

The list of built-in functions is in Chapter 9. Other functions can be added by the user.

在发出其中一些用户不信任其他用户的数据库中的查询时,在编写函数调用时请遵循 Section 10.3中的安全预防措施。

When issuing queries in a database where some users mistrust other users, observe security precautions from Section 10.3 when writing function calls.

参数可以选择附加名称。有关详细信息,请参阅 Section 4.3

The arguments can optionally have names attached. See Section 4.3 for details.

Note

一个函数采用一个复合类型参数,可以使用字段选择语法进行调用,反之亦然,也可以采用函数风格书写字段选择。也就是说,符号_col(table)_和_table.col_可以互换使用。这种行为并不符合 SQL 标准,但 PostgreSQL 会提供这种行为,因为它允许使用函数模拟“计算字段”。如需了解更多信息,请参阅 Section 8.16.5

A function that takes a single argument of composite type can optionally be called using field-selection syntax, and conversely field selection can be written in functional style. That is, the notations col(table) and table.col are interchangeable. This behavior is not SQL-standard but is provided in PostgreSQL because it allows use of functions to emulate “computed fields”. For more information see Section 8.16.5.

4.2.7. Aggregate Expressions #

aggregate expression 表示聚合函数在查询选择的行内应用。聚合函数将多个输入值减少为一个输出值,例如输入值的和或平均值。聚合表达式的语法是以下之一:

An aggregate expression represents the application of an aggregate function across the rows selected by a query. An aggregate function reduces multiple inputs to a single output value, such as the sum or average of the inputs. The syntax of an aggregate expression is one of the following:

aggregate_name (expression [ , ... ] [ order_by_clause ] ) [ FILTER ( WHERE filter_clause ) ]
aggregate_name (ALL expression [ , ... ] [ order_by_clause ] ) [ FILTER ( WHERE filter_clause ) ]
aggregate_name (DISTINCT expression [ , ... ] [ order_by_clause ] ) [ FILTER ( WHERE filter_clause ) ]
aggregate_name ( * ) [ FILTER ( WHERE filter_clause ) ]
aggregate_name ( [ expression [ , ... ] ] ) WITHIN GROUP ( order_by_clause ) [ FILTER ( WHERE filter_clause ) ]

其中 aggregate_name 是以前定义的聚合(可能使用模式名限定),而 expression 是不自己包含聚合表达式或窗口函数调用的任何值表达式。下面描述了可选的 order_by_clausefilter_clause

where aggregate_name is a previously defined aggregate (possibly qualified with a schema name) and expression is any value expression that does not itself contain an aggregate expression or a window function call. The optional order_by_clause and filter_clause are described below.

聚合表达式的第一种形式为每输入行调用一次聚合。第二种形式与第一种形式相同,因为 ALL 是默认形式。第三种形式为输入行中发现的表达式的每个不同值(或多个表达式的不同值集)调用一次聚合。第四种形式对每输入行调用一次聚合;由于没有指定具体的输入值,它通常仅对 count(*) 聚合函数有用。最后一种形式用于下面描述的 ordered-set 聚合函数。

The first form of aggregate expression invokes the aggregate once for each input row. The second form is the same as the first, since ALL is the default. The third form invokes the aggregate once for each distinct value of the expression (or distinct set of values, for multiple expressions) found in the input rows. The fourth form invokes the aggregate once for each input row; since no particular input value is specified, it is generally only useful for the count(*) aggregate function. The last form is used with ordered-set aggregate functions, which are described below.

大多数聚合函数会忽略 null 输入,从而丢弃表达式之一或全部产生 null 的行。除非另有指定,否则可以假定这对于所有内置聚合都是正确的。

Most aggregate functions ignore null inputs, so that rows in which one or more of the expression(s) yield null are discarded. This can be assumed to be true, unless otherwise specified, for all built-in aggregates.

例如,count(*) 会生成输入行的总数;count(f1) 会生成 f1 不为 null 的输入行的数量,因为 count 会忽略空值;而 count(distinct f1) 会生成 f1 的不同非空值的数目。

For example, count(*) yields the total number of input rows; count(f1) yields the number of input rows in which f1 is non-null, since count ignores nulls; and count(distinct f1) yields the number of distinct non-null values of f1.

通常,输入行以未指定顺序馈送到聚合函数。在许多情况下,这一点无关紧要;例如,min_产生相同的 resultaat,无论以什么顺序接收输入。但是,某些聚合函数(例如 _array_agg_和 _string_agg)产生的结果取决于输入行的顺序。使用此类聚合时,可以使用可选的 _order_by_clause_指定所需的顺序。_order_by_clause_具有与查询级别 _ORDER BY_子句相同的语法,如 Section 7.5中所述,但其表达式始终是表达式,不能是输出列名或数字。例如:

Ordinarily, the input rows are fed to the aggregate function in an unspecified order. In many cases this does not matter; for example, min produces the same result no matter what order it receives the inputs in. However, some aggregate functions (such as array_agg and string_agg) produce results that depend on the ordering of the input rows. When using such an aggregate, the optional order_by_clause can be used to specify the desired ordering. The order_by_clause has the same syntax as for a query-level ORDER BY clause, as described in Section 7.5, except that its expressions are always just expressions and cannot be output-column names or numbers. For example:

SELECT array_agg(a ORDER BY b DESC) FROM table;

在处理多参数聚合函数时,请注意,ORDER BY 子句位于所有聚合参数之后。例如,请编写以下内容:

When dealing with multiple-argument aggregate functions, note that the ORDER BY clause goes after all the aggregate arguments. For example, write this:

SELECT string_agg(a, ',' ORDER BY a) FROM table;

而不是以下内容:

not this:

SELECT string_agg(a ORDER BY a, ',') FROM table;  -- incorrect

后者在语法上是有效的,但它表示一个单参数聚合函数的调用,带有两个 ORDER BY 键(第二个键相当无用,因为它是一个常量)。

The latter is syntactically valid, but it represents a call of a single-argument aggregate function with two ORDER BY keys (the second one being rather useless since it’s a constant).

如果除了 order_by_clause 之外还指定了 DISTINCT,则所有 ORDER BY 表达式都必须与聚合的常规参数匹配;也就是说,您不能对未包含在 DISTINCT 列表中的表达式进行排序。

If DISTINCT is specified in addition to an order_by_clause, then all the ORDER BY expressions must match regular arguments of the aggregate; that is, you cannot sort on an expression that is not included in the DISTINCT list.

Note

在聚合函数中指定 DISTINCTORDER BY 的能力是 PostgreSQL 的扩展。

The ability to specify both DISTINCT and ORDER BY in an aggregate function is a PostgreSQL extension.

在常规参数列表中放置 ORDER BY,如到目前为止所述,用于为通用和统计聚合对输入行进行排序,其中排序是可选的。有一类聚合函数称为 ordered-set aggregates,其中 order_by_clauserequired,通常是因为聚合的计算只能根据其输入行的特定顺序才有意义。有序集聚合的典型示例包括排名和百分比计算。对于有序集聚合,order_by_clause 写在 WITHIN GROUP (…​) 内,如上面所示的最终语法备选方案中。order_by_clause 中的表达式每个输入行评估一次,就像常规聚合参数一样,按照 order_by_clause 的要求进行排序,并作为输入参数送入聚合函数中。(这与非 WITHIN GROUP order_by_clause 的情况不同,后者不被视为聚合函数的参数。)WITHIN GROUP 之前的参数表达式(如果有的话)称为 direct arguments,以区别于 order_by_clause 中列出的 aggregated arguments。与常规聚合参数不同,直接参数每个聚合调用只评估一次,而不是每个输入行评估一次。这意味着它们只能包含变量,如果这些变量按 GROUP BY 分组;这种限制与直接参数根本不在聚合表达式中相同。直接参数通常用于百分比等内容,它仅作为每次聚合计算的一个值才有意义。直接参数列表可以为空;在这种情况下,仅编写 (),而不是 (*)。(PostgreSQL 实际上都会接受这两种拼写,但只有第一种方式符合 SQL 标准。)

Placing ORDER BY within the aggregate’s regular argument list, as described so far, is used when ordering the input rows for general-purpose and statistical aggregates, for which ordering is optional. There is a subclass of aggregate functions called ordered-set aggregates for which an order_by_clause is required, usually because the aggregate’s computation is only sensible in terms of a specific ordering of its input rows. Typical examples of ordered-set aggregates include rank and percentile calculations. For an ordered-set aggregate, the order_by_clause is written inside WITHIN GROUP (…​), as shown in the final syntax alternative above. The expressions in the order_by_clause are evaluated once per input row just like regular aggregate arguments, sorted as per the order_by_clause's requirements, and fed to the aggregate function as input arguments. (This is unlike the case for a non-WITHIN GROUP order_by_clause, which is not treated as argument(s) to the aggregate function.) The argument expressions preceding WITHIN GROUP, if any, are called direct arguments to distinguish them from the aggregated arguments listed in the order_by_clause. Unlike regular aggregate arguments, direct arguments are evaluated only once per aggregate call, not once per input row. This means that they can contain variables only if those variables are grouped by GROUP BY; this restriction is the same as if the direct arguments were not inside an aggregate expression at all. Direct arguments are typically used for things like percentile fractions, which only make sense as a single value per aggregation calculation. The direct argument list can be empty; in this case, write just () not (*). (PostgreSQL will actually accept either spelling, but only the first way conforms to the SQL standard.)

有序集聚合调用的示例是:

An example of an ordered-set aggregate call is:

SELECT percentile_cont(0.5) WITHIN GROUP (ORDER BY income) FROM households;
 percentile_cont
-----------------
           50489

households 表获取 income 列的第 50 个百分位数或中值。此处,0.5 是直接参数;按行变化的百分位数没有任何意义。

which obtains the 50th percentile, or median, value of the income column from table households. Here, 0.5 is a direct argument; it would make no sense for the percentile fraction to be a value varying across rows.

如果指定了 FILTER,那么只有 filter_clause 求值为 true 的输入行才会送入聚合函数;其他行将被丢弃。例如:

If FILTER is specified, then only the input rows for which the filter_clause evaluates to true are fed to the aggregate function; other rows are discarded. For example:

SELECT
    count(*) AS unfiltered,
    count(*) FILTER (WHERE i < 5) AS filtered
FROM generate_series(1,10) AS s(i);
 unfiltered | filtered
------------+----------
         10 |        4
(1 row)

有关预定义集合函数的介绍请参见 Section 9.21。 用户可以添加其他集合函数。

The predefined aggregate functions are described in Section 9.21. Other aggregate functions can be added by the user.

聚合表达式只能出现在 SELECT 命令的结果列表或 HAVING 子句中。在其他子句(例如 WHERE)中是禁止的,因为在形成聚合结果之前会对这些子句进行逻辑运算。

An aggregate expression can only appear in the result list or HAVING clause of a SELECT command. It is forbidden in other clauses, such as WHERE, because those clauses are logically evaluated before the results of aggregates are formed.

当聚合表达式出现在子查询中 (请参见 Section 4.2.11 and Section 9.23) 时, 通常在子查询行上评估聚合。 但如果聚合参数(以及 filter_clause_如果有的话)仅包含外部级别变量,则会出现一个异常:聚合属于最接近的外部级别,并在该查询的行上评估。 然后聚合表达式作为整体出现其它的子查询的外部引用,并充当该子查询的任意一个评估常量的作用。 仅出现在结果列表或 _HAVING 子句中的限制相对于聚合所属的查询级别应用。

When an aggregate expression appears in a subquery (see Section 4.2.11 and Section 9.23), the aggregate is normally evaluated over the rows of the subquery. But an exception occurs if the aggregate’s arguments (and filter_clause if any) contain only outer-level variables: the aggregate then belongs to the nearest such outer level, and is evaluated over the rows of that query. The aggregate expression as a whole is then an outer reference for the subquery it appears in, and acts as a constant over any one evaluation of that subquery. The restriction about appearing only in the result list or HAVING clause applies with respect to the query level that the aggregate belongs to.

4.2.8. Window Function Calls #

window function call 代表对查询所选行的一部分应用类似聚合的函数。与非窗口聚合调用不同,它与将所选行分组到单个输出行中无关——每一行在查询输出中仍然是单独的。然而,窗口函数可以访问根据窗口函数调用的分组规范 (PARTITION BY 列表) 而成为当前行组的全部行。窗口函数调用的语法是以下之一:

A window function call represents the application of an aggregate-like function over some portion of the rows selected by a query. Unlike non-window aggregate calls, this is not tied to grouping of the selected rows into a single output row — each row remains separate in the query output. However the window function has access to all the rows that would be part of the current row’s group according to the grouping specification (PARTITION BY list) of the window function call. The syntax of a window function call is one of the following:

function_name ([expression [, expression ... ]]) [ FILTER ( WHERE filter_clause ) ] OVER window_name
function_name ([expression [, expression ... ]]) [ FILTER ( WHERE filter_clause ) ] OVER ( window_definition )
function_name ( * ) [ FILTER ( WHERE filter_clause ) ] OVER window_name
function_name ( * ) [ FILTER ( WHERE filter_clause ) ] OVER ( window_definition )

其中 window_definition 语法为

where window_definition has the syntax

[ existing_window_name ]
[ PARTITION BY expression [, ...] ]
[ ORDER BY expression [ ASC | DESC | USING operator ] [ NULLS { FIRST | LAST } ] [, ...] ]
[ frame_clause ]

可选的 frame_clause 可以是以下之一

The optional frame_clause can be one of

{ RANGE | ROWS | GROUPS } frame_start [ frame_exclusion ]
{ RANGE | ROWS | GROUPS } BETWEEN frame_start AND frame_end [ frame_exclusion ]

其中 frame_startframe_end 可以是以下之一

where frame_start and frame_end can be one of

UNBOUNDED PRECEDING
offset PRECEDING
CURRENT ROW
offset FOLLOWING
UNBOUNDED FOLLOWING

frame_exclusion 可以是以下之一

and frame_exclusion can be one of

EXCLUDE CURRENT ROW
EXCLUDE GROUP
EXCLUDE TIES
EXCLUDE NO OTHERS

在此处,expression 代表任何值表达式,其本身不包含窗口函数调用。

Here, expression represents any value expression that does not itself contain window function calls.

window_name 是对查询 WINDOW 子句中定义的命名窗口规范的引用。此外,可以使用与在 WINDOW 子句中定义命名窗口相同的语法,在括号中给出一个完整的 window_definition ;有关详细信息,请参阅 SELECT 参考页。值得指出的是, OVER wnameOVER (wname …​) 并不完全等价;后者意味着复制和修改窗口定义,如果引用的窗口规范包含帧子句,则会拒绝。

window_name is a reference to a named window specification defined in the query’s WINDOW clause. Alternatively, a full window_definition can be given within parentheses, using the same syntax as for defining a named window in the WINDOW clause; see the SELECT reference page for details. It’s worth pointing out that OVER wname is not exactly equivalent to OVER (wname …​); the latter implies copying and modifying the window definition, and will be rejected if the referenced window specification includes a frame clause.

PARTITION BY 子句将查询的行分组到 partitions 中,窗口函数会单独处理这些行。PARTITION BY 的工作方式类似于查询级别的 GROUP BY 子句,除了它的表达式始终只是表达式,不能是输出列名或数字。如果不用 PARTITION BY,查询生成的所有行将被视为一个分区。ORDER BY 子句决定了窗口函数将如何处理分区行。它的工作方式类似于查询级别的 ORDER BY 子句,但同样也不能使用输出列名或数字。如果不使用 ORDER BY,行将按未指定顺序处理。

The PARTITION BY clause groups the rows of the query into partitions, which are processed separately by the window function. PARTITION BY works similarly to a query-level GROUP BY clause, except that its expressions are always just expressions and cannot be output-column names or numbers. Without PARTITION BY, all rows produced by the query are treated as a single partition. The ORDER BY clause determines the order in which the rows of a partition are processed by the window function. It works similarly to a query-level ORDER BY clause, but likewise cannot use output-column names or numbers. Without ORDER BY, rows are processed in an unspecified order.

frame_clause 指定了构成 window frame 的行集,对于在帧而不是整个分区上执行的那些窗口函数来说,这是当前分区的子集。帧中的行集可能会根据当前行为哪行而有所不同。帧可以在 RANGEROWSGROUPS 模式下指定;在每种情况下,它从 frame_start 运行到 frame_end。如果省略 frame_end,结尾将默认为 CURRENT ROW

The frame_clause specifies the set of rows constituting the window frame, which is a subset of the current partition, for those window functions that act on the frame instead of the whole partition. The set of rows in the frame can vary depending on which row is the current row. The frame can be specified in RANGE, ROWS or GROUPS mode; in each case, it runs from the frame_start to the frame_end. If frame_end is omitted, the end defaults to CURRENT ROW.

frame_start UNBOUNDED PRECEDING 意味着帧从分区的首行开始,类似地,frame_end UNBOUNDED FOLLOWING 意味着帧以分区的末行为结尾。

A frame_start of UNBOUNDED PRECEDING means that the frame starts with the first row of the partition, and similarly a frame_end of UNBOUNDED FOLLOWING means that the frame ends with the last row of the partition.

RANGEGROUPS 模式中,frame_start CURRENT ROW 意味着帧从当前行的第一个 peer 行开始(窗口的 ORDER BY 子句将作为等效于当前行的行进行排序),而 frame_end CURRENT ROW 意味着帧以当前行的最后一个对等行结尾。在 ROWS 模式中,CURRENT ROW 仅仅意味着当前行。

In RANGE or GROUPS mode, a frame_start of CURRENT ROW means the frame starts with the current row’s first peer row (a row that the window’s ORDER BY clause sorts as equivalent to the current row), while a frame_end of CURRENT ROW means the frame ends with the current row’s last peer row. In ROWS mode, CURRENT ROW simply means the current row.

offset PRECEDINGoffset FOLLOWING 帧选项中,offset 必须是不包含任何变量、聚合函数或窗口函数的表达式。offset 的含义取决于帧模式:

In the offset PRECEDING and offset FOLLOWING frame options, the offset must be an expression not containing any variables, aggregate functions, or window functions. The meaning of the offset depends on the frame mode:

在任何情况下,到帧结尾的距离都受限于到分区结尾的距离,因此对于分区两端的行来说,帧可能包含的行比其他地方少。

In any case, the distance to the end of the frame is limited by the distance to the end of the partition, so that for rows near the partition ends the frame might contain fewer rows than elsewhere.

请注意,在 ROWSGROUPS 两种模式下,0 PRECEDING0 FOLLOWING 等同于 CURRENT ROW。对于数据类型的特定含义的“零”,在 RANGE 模式中通常也能成立。

Notice that in both ROWS and GROUPS mode, 0 PRECEDING and 0 FOLLOWING are equivalent to CURRENT ROW. This normally holds in RANGE mode as well, for an appropriate data-type-specific meaning of “zero”.

frame_exclusion 选项允许排除帧周围的当前行,即使它们会根据帧开始和帧结束选项包括在内。EXCLUDE CURRENT ROW 从帧中排除当前行。EXCLUDE GROUP 从帧中排除当前行及其排序对等行。EXCLUDE TIES 从帧中排除当前行的任何对等行,但不是当前行本身。EXCLUDE NO OTHERS 只是明确指定默认行为,即不排除当前行及其对等行。

The frame_exclusion option allows rows around the current row to be excluded from the frame, even if they would be included according to the frame start and frame end options. EXCLUDE CURRENT ROW excludes the current row from the frame. EXCLUDE GROUP excludes the current row and its ordering peers from the frame. EXCLUDE TIES excludes any peers of the current row from the frame, but not the current row itself. EXCLUDE NO OTHERS simply specifies explicitly the default behavior of not excluding the current row or its peers.

默认的成帧选项是 RANGE UNBOUNDED PRECEDING,它与 RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW 相同。使用 ORDER BY,会将帧设置为从分区开始到当前行的最后一个 ORDER BY 对等行。如果不用 ORDER BY,则意味着分区的全部行都包含在窗口帧中,因为全部行都成为当前行的对等行。

The default framing option is RANGE UNBOUNDED PRECEDING, which is the same as RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW. With ORDER BY, this sets the frame to be all rows from the partition start up through the current row’s last ORDER BY peer. Without ORDER BY, this means all rows of the partition are included in the window frame, since all rows become peers of the current row.

限制是 frame_start 不能是 UNBOUNDED FOLLOWINGframe_end 不能是 UNBOUNDED PRECEDING,并且 frame_end 选择不得出现在 frame_startframe_end 选项上述列表中 frame_start 选择之前——例如,不允许对 RANGE BETWEEN CURRENT ROW AND _offset PRECEDING_ 使用。但允许对 ROWS BETWEEN 7 PRECEDING AND 8 PRECEDING 使用,即使它永远不会选择任何行。

Restrictions are that frame_start cannot be UNBOUNDED FOLLOWING, frame_end cannot be UNBOUNDED PRECEDING, and the frame_end choice cannot appear earlier in the above list of frame_start and frame_end options than the frame_start choice does — for example RANGE BETWEEN CURRENT ROW AND _offset PRECEDING_ is not allowed. But, for example, ROWS BETWEEN 7 PRECEDING AND 8 PRECEDING is allowed, even though it would never select any rows.

如果指定了 FILTER,则仅当 filter_clause 对其求值为 true 的输入行才会被馈送到窗口函数;其他行将被丢弃。只有是聚合的窗口函数才接受 FILTER 子句。

If FILTER is specified, then only the input rows for which the filter_clause evaluates to true are fed to the window function; other rows are discarded. Only window functions that are aggregates accept a FILTER clause.

有关 Table 9.64 中所述的内置窗口函数的详细信息。 用户可以添加其他窗口函数。 此外,任何内置或用户定义的一般用途或统计聚合都可以用作窗口函数。 (目前无法将有序集和假设集聚合用作窗口函数。)

The built-in window functions are described in Table 9.64. Other window functions can be added by the user. Also, any built-in or user-defined general-purpose or statistical aggregate can be used as a window function. (Ordered-set and hypothetical-set aggregates cannot presently be used as window functions.)

使用 * 的语法用于将无参数聚合函数作为窗口函数进行调用,例如 count(*) OVER (PARTITION BY x ORDER BY y)。通常不用星号 (*) 用于窗口专用函数。窗口专用函数不允许在函数参数列表中使用 DISTINCTORDER BY

The syntaxes using * are used for calling parameter-less aggregate functions as window functions, for example count(*) OVER (PARTITION BY x ORDER BY y). The asterisk (*) is customarily not used for window-specific functions. Window-specific functions do not allow DISTINCT or ORDER BY to be used within the function argument list.

仅允许在查询的 SELECT 列表和 ORDER BY 子句中调用窗口函数。

Window function calls are permitted only in the SELECT list and the ORDER BY clause of the query.

有关窗口函数的详细信息,请参见 Section 3.5Section 9.22Section 7.2.5

More information about window functions can be found in Section 3.5, Section 9.22, and Section 7.2.5.

4.2.9. Type Casts #

类型转换指定从一种数据类型转换为另一种数据类型。PostgreSQL 接受针对类型转换的两种等效语法:

A type cast specifies a conversion from one data type to another. PostgreSQL accepts two equivalent syntaxes for type casts:

CAST ( expression AS type )
expression::type

CAST 语法符合 SQL;带有 :: 的语法是 PostgreSQL 的历史用法。

The CAST syntax conforms to SQL; the syntax with :: is historical PostgreSQL usage.

当转换应用于已知类型的值表达式时,它表示运行时类型转换。 只有在定义合适的类型转换操作时,转换才能成功。 请注意,这与 Section 4.1.2.7 中所示的转换与常量一起使用的情况略有不同。 应用于无修饰字符串文字的类型转换表示将类型最初分配给文字常量值,因此对于任何类型来说都将成功(如果字符串文字的内容是数据类型的可接受的输入语法)。

When a cast is applied to a value expression of a known type, it represents a run-time type conversion. The cast will succeed only if a suitable type conversion operation has been defined. Notice that this is subtly different from the use of casts with constants, as shown in Section 4.1.2.7. A cast applied to an unadorned string literal represents the initial assignment of a type to a literal constant value, and so it will succeed for any type (if the contents of the string literal are acceptable input syntax for the data type).

如果对于值表达式必须产生的类型没有任何歧义(例如,当它被分配给表字段时),通常可以省略显式类型转换;在这种情况下,系统会自动应用类型转换。然而,只有在系统目录中将转换标记为“可以隐式应用”时,才会进行自动转换。其他转换必须使用显式转换语法进行调用。此限制是为了防止令人惊讶的转换被悄悄应用。

An explicit type cast can usually be omitted if there is no ambiguity as to the type that a value expression must produce (for example, when it is assigned to a table column); the system will automatically apply a type cast in such cases. However, automatic casting is only done for casts that are marked “OK to apply implicitly” in the system catalogs. Other casts must be invoked with explicit casting syntax. This restriction is intended to prevent surprising conversions from being applied silently.

还可以使用类似函数的语法指定类型转换:

It is also possible to specify a type cast using a function-like syntax:

typename ( expression )

但是,这仅适用于名称也作为函数名称有效的类型。例如,double precision 不能以这种方式使用,但等效的 float8 可以。此外,名称 intervaltimetimestamp 只能以这种方式使用,如果它们被双引号引用,这是因为存在语法冲突。因此,使用类似函数的转换语法的做法会导致不一致,并且很可能应该避免。

However, this only works for types whose names are also valid as function names. For example, double precision cannot be used this way, but the equivalent float8 can. Also, the names interval, time, and timestamp can only be used in this fashion if they are double-quoted, because of syntactic conflicts. Therefore, the use of the function-like cast syntax leads to inconsistencies and should probably be avoided.

Note

类似函数的语法实际上只是一个函数调用。当使用两种标准转换语法之一执行运行时转换时,它将在内部调用已注册的函数来执行转换。按照惯例,这些转换函数与其输出类型具有相同的名称,因此“类似函数的语法”只不过是直接调用基础转换函数。显然,这不是可移植应用程序应该依赖的东西。有关更多详细信息,请参阅 CREATE CAST

The function-like syntax is in fact just a function call. When one of the two standard cast syntaxes is used to do a run-time conversion, it will internally invoke a registered function to perform the conversion. By convention, these conversion functions have the same name as their output type, and thus the “function-like syntax” is nothing more than a direct invocation of the underlying conversion function. Obviously, this is not something that a portable application should rely on. For further details see CREATE CAST.

4.2.10. Collation Expressions #

COLLATE 子句会覆盖表达式的校对规则。它附加到它适用的表达式上:

The COLLATE clause overrides the collation of an expression. It is appended to the expression it applies to:

expr COLLATE collation

其中 collation 是一个可能合格的方案标识符。COLLATE 子句的绑定权重比运算符高;必要时可以使用括号。

where collation is a possibly schema-qualified identifier. The COLLATE clause binds tighter than operators; parentheses can be used when necessary.

如果未明确指定校对规则,则数据库系统会从表达式中涉及的字段派生校对规则,或者如果没有字段涉及表达式,则系统会默认使用数据库的默认校对规则。

If no collation is explicitly specified, the database system either derives a collation from the columns involved in the expression, or it defaults to the default collation of the database if no column is involved in the expression.

COLLATE 子句的两个常见用法是覆盖 ORDER BY 子句中的排序顺序,例如:

The two common uses of the COLLATE clause are overriding the sort order in an ORDER BY clause, for example:

SELECT a, b, c FROM tbl WHERE ... ORDER BY a COLLATE "C";

并覆盖具有区分语言环境结果的函数或运算符调用的校对规则,例如:

and overriding the collation of a function or operator call that has locale-sensitive results, for example:

SELECT * FROM tbl WHERE a > 'foo' COLLATE "C";

请注意,在后一种情况下,_COLLATE_子句附加到我们希望影响的运算符的输入参数。 _COLLATE_子句附加到运算符或函数调用的哪个参数并不重要,因为运算符或函数应用的排序通过考虑所有参数来导出,并且显式的 _COLLATE_子句将覆盖所有其他参数的排序。 (但是,将不匹配的 _COLLATE_子句附加到多个参数中,则为错误。 有关更多详细信息,请参见 Section 24.2。)因此,这与前面的示例给出的结果相同:

Note that in the latter case the COLLATE clause is attached to an input argument of the operator we wish to affect. It doesn’t matter which argument of the operator or function call the COLLATE clause is attached to, because the collation that is applied by the operator or function is derived by considering all arguments, and an explicit COLLATE clause will override the collations of all other arguments. (Attaching non-matching COLLATE clauses to more than one argument, however, is an error. For more details see Section 24.2.) Thus, this gives the same result as the previous example:

SELECT * FROM tbl WHERE a COLLATE "C" > 'foo';

但这是一个错误:

But this is an error:

SELECT * FROM tbl WHERE (a > 'foo') COLLATE "C";

因为它试图对_>_运算符(非排序数据类型_boolean_)的结果应用排序规则。

because it attempts to apply a collation to the result of the > operator, which is of the non-collatable data type boolean.

4.2.11. Scalar Subqueries #

标量子查询是一个用括号括起来的普通 _SELECT_查询,该查询返回一行一列。 (有关如何编写查询的信息,请参见 Chapter 7。)_SELECT_查询被执行,并且所返回的单个值在周围的值表达式中使用。 将返回多行或多列的查询用作标量子查询是一个错误。 (但是,如果在某一特定执行过程中,子查询不返回任何行,则不会出现错误;标量结果被视为 null。)子查询可以引用周围查询的变量,该查询将在子查询的任何一个评估过程中起常量的作用。 有关涉及子查询的其他表达式的详细信息,请参见 Section 9.23

A scalar subquery is an ordinary SELECT query in parentheses that returns exactly one row with one column. (See Chapter 7 for information about writing queries.) The SELECT query is executed and the single returned value is used in the surrounding value expression. It is an error to use a query that returns more than one row or more than one column as a scalar subquery. (But if, during a particular execution, the subquery returns no rows, there is no error; the scalar result is taken to be null.) The subquery can refer to variables from the surrounding query, which will act as constants during any one evaluation of the subquery. See also Section 9.23 for other expressions involving subqueries.

例如,以下查询项找出每个州的最大的城市人口:

For example, the following finds the largest city population in each state:

SELECT name, (SELECT max(pop) FROM cities WHERE cities.state = states.name)
    FROM states;

4.2.12. Array Constructors #

数组构造器是一种表达式,它使用成员元素的值建立一个数组值。 一个简单的数组构造器由关键字 ARRAY、左方括号 [、数组元素值的表达式列表(用逗号分隔)、最后右方括号 _]_组成。 例如:

An array constructor is an expression that builds an array value using values for its member elements. A simple array constructor consists of the key word ARRAY, a left square bracket [, a list of expressions (separated by commas) for the array element values, and finally a right square bracket ]. For example:

SELECT ARRAY[1,2,3+4];
  array
---------
 {1,2,7}
(1 row)

默认情况下,数组元素类型是成员表达式的公用类型,使用与 _UNION_或 _CASE_构造器相同的规则确定(请参见 Section 10.5。你也可以通过将数组构造器显式转换为所需的类型来覆盖此项,例如:

By default, the array element type is the common type of the member expressions, determined using the same rules as for UNION or CASE constructs (see Section 10.5). You can override this by explicitly casting the array constructor to the desired type, for example:

SELECT ARRAY[1,2,22.7]::integer[];
  array
----------
 {1,2,23}
(1 row)

这与将每个表达式分别转换为数组元素类型具有相同的效果。 有关类型转换的更多信息,请参见 Section 4.2.9

This has the same effect as casting each expression to the array element type individually. For more on casting, see Section 4.2.9.

可以通过嵌套数组构造器来构建多维数组值。在内部构造器中,可以省略关键词_ARRAY_。例如,这些产生相同的结果:

Multidimensional array values can be built by nesting array constructors. In the inner constructors, the key word ARRAY can be omitted. For example, these produce the same result:

SELECT ARRAY[ARRAY[1,2], ARRAY[3,4]];
     array
---------------
 {{1,2},{3,4}}
(1 row)

SELECT ARRAY[[1,2],[3,4]];
     array
---------------
 {{1,2},{3,4}}
(1 row)

由于多维数组必须是矩形,因此同一级别的内部构造器必须生成大小相同的子数组。应用于外部_ARRAY_构造器的任何强制转换都会自动传播到所有内部构造器。

Since multidimensional arrays must be rectangular, inner constructors at the same level must produce sub-arrays of identical dimensions. Any cast applied to the outer ARRAY constructor propagates automatically to all the inner constructors.

多维数组构造器元素可以生成适当类型的数组的任何东西,而不仅仅是_ARRAY_构造。例如:

Multidimensional array constructor elements can be anything yielding an array of the proper kind, not only a sub-ARRAY construct. For example:

CREATE TABLE arr(f1 int[], f2 int[]);

INSERT INTO arr VALUES (ARRAY[[1,2],[3,4]], ARRAY[[5,6],[7,8]]);

SELECT ARRAY[f1, f2, '{{9,10},{11,12}}'::int[]] FROM arr;
                     array
------------------------------------------------
 {{{1,2},{3,4}},{{5,6},{7,8}},{{9,10},{11,12}}}
(1 row)

你可以构建一个空数组,但由于不可能存在没有类型的数组,因此你必须显式将你的空数组强制转换为所需的类型。例如:

You can construct an empty array, but since it’s impossible to have an array with no type, you must explicitly cast your empty array to the desired type. For example:

SELECT ARRAY[]::integer[];
 array
-------
 {}
(1 row)

还可以根据子查询的结果构建数组。在此形式中,数组构造器使用关键词_ARRAY_编写,后跟有括号(无方括号)的子查询。例如:

It is also possible to construct an array from the results of a subquery. In this form, the array constructor is written with the key word ARRAY followed by a parenthesized (not bracketed) subquery. For example:

SELECT ARRAY(SELECT oid FROM pg_proc WHERE proname LIKE 'bytea%');
                              array
------------------------------------------------------------------
 {2011,1954,1948,1952,1951,1244,1950,2005,1949,1953,2006,31,2412}
(1 row)

SELECT ARRAY(SELECT ARRAY[i, i*2] FROM generate_series(1,5) AS a(i));
              array
----------------------------------
 {{1,2},{2,4},{3,6},{4,8},{5,10}}
(1 row)

子查询必须返回单列。如果子查询的输出列为非数组类型,则生成的一维数组将为子查询结果中的每一行设置一个元素,其元素类型与子查询的输出列的元素类型相匹配。如果子查询的输出列为数组类型,则结果将是相同类型但维度高一维的数组;在这种情况下,所有子查询行必须生成维数相同的数组,否则结果将不是矩形。

The subquery must return a single column. If the subquery’s output column is of a non-array type, the resulting one-dimensional array will have an element for each row in the subquery result, with an element type matching that of the subquery’s output column. If the subquery’s output column is of an array type, the result will be an array of the same type but one higher dimension; in this case all the subquery rows must yield arrays of identical dimensionality, else the result would not be rectangular.

使用 _ARRAY_建立的数组值的索引始终从 1 开始。 有关数组的更多信息,请参见 Section 8.15

The subscripts of an array value built with ARRAY always begin with one. For more information about arrays, see Section 8.15.

4.2.13. Row Constructors #

行构造器是一个表达式,用于使用成员字段的值构建行值(也称为复合值)。行构造器由关键词_ROW_、一个左括号、零个或多个由行字段值(由逗号分隔)组成的表达式,最后是一个右括号组成。例如:

A row constructor is an expression that builds a row value (also called a composite value) using values for its member fields. A row constructor consists of the key word ROW, a left parenthesis, zero or more expressions (separated by commas) for the row field values, and finally a right parenthesis. For example:

SELECT ROW(1,2.5,'this is a test');

当列表中有多个表达式时,关键词_ROW_是可选的。

The key word ROW is optional when there is more than one expression in the list.

行构造器可以包含 rowvalue_.*, which will be expanded to a list of the elements of the row value, just as occurs when the _.*_语法在 _SELECT_列表的顶层中使用(请参见 Section 8.16.5)。 例如,如果表 _t_具有列 _f1_和 _f2,则它们相同:

A row constructor can include the syntax rowvalue_.*, which will be expanded to a list of the elements of the row value, just as occurs when the _.* syntax is used at the top level of a SELECT list (see Section 8.16.5). For example, if table t has columns f1 and f2, these are the same:

SELECT ROW(t.*, 42) FROM t;
SELECT ROW(t.f1, t.f2, 42) FROM t;

Note

在 PostgreSQL 8.2 之前,. syntax was not expanded in row constructors, so that writing ROW(t., 42) 创建了一个两字段行,其第一个字段是另一个行值。新行为通常更有用。如果您需要嵌套行值的旧行为,请不使用 .* 编写内部行值,例如 ROW(t, 42)

Before PostgreSQL 8.2, the . syntax was not expanded in row constructors, so that writing ROW(t., 42) created a two-field row whose first field was another row value. The new behavior is usually more useful. If you need the old behavior of nested row values, write the inner row value without .*, for instance ROW(t, 42).

默认情况下,_ROW_表达式创建的值是匿名记录类型。如果需要,可以将它强制转换为命名复合类型——表的行类型,或使用_CREATE TYPE AS_创建的复合类型。为了避免歧义,可能需要显式强制转换。例如:

By default, the value created by a ROW expression is of an anonymous record type. If necessary, it can be cast to a named composite type — either the row type of a table, or a composite type created with CREATE TYPE AS. An explicit cast might be needed to avoid ambiguity. For example:

CREATE TABLE mytable(f1 int, f2 float, f3 text);

CREATE FUNCTION getf1(mytable) RETURNS int AS 'SELECT $1.f1' LANGUAGE SQL;

-- No cast needed since only one getf1() exists
SELECT getf1(ROW(1,2.5,'this is a test'));
 getf1
-------
     1
(1 row)

CREATE TYPE myrowtype AS (f1 int, f2 text, f3 numeric);

CREATE FUNCTION getf1(myrowtype) RETURNS int AS 'SELECT $1.f1' LANGUAGE SQL;

-- Now we need a cast to indicate which function to call:
SELECT getf1(ROW(1,2.5,'this is a test'));
ERROR:  function getf1(record) is not unique

SELECT getf1(ROW(1,2.5,'this is a test')::mytable);
 getf1
-------
     1
(1 row)

SELECT getf1(CAST(ROW(11,'this is a test',2.5) AS myrowtype));
 getf1
-------
    11
(1 row)

行构造器可用于构建要存储在复合类型表列中、或要传递给接受复合参数的函数的复合值。此外,还可以比较两个行值或使用_IS NULL_或_IS NOT NULL_测试行,例如:

Row constructors can be used to build composite values to be stored in a composite-type table column, or to be passed to a function that accepts a composite parameter. Also, it is possible to compare two row values or test a row with IS NULL or IS NOT NULL, for example:

SELECT ROW(1,2.5,'this is a test') = ROW(1, 3, 'not the same');

SELECT ROW(table.*) IS NULL FROM table;  -- detect all-null rows

有关详细信息,请参见 Section 9.24。正如 Section 9.23中所讨论的,行构造器也可以结合子查询使用。

For more detail see Section 9.24. Row constructors can also be used in connection with subqueries, as discussed in Section 9.23.

4.2.14. Expression Evaluation Rules #

子表达式的求值顺序没有规定。具体来说,运算符或函数的输入不一定从左到右或按其他任何固定顺序进行求值。

The order of evaluation of subexpressions is not defined. In particular, the inputs of an operator or function are not necessarily evaluated left-to-right or in any other fixed order.

此外,如果表达式的结果可以通过只求值它的一部分来确定,那么其他子表达式可能根本不会被求值。例如,如果写:

Furthermore, if the result of an expression can be determined by evaluating only some parts of it, then other subexpressions might not be evaluated at all. For instance, if one wrote:

SELECT true OR somefunc();

那么 somefunc()(可能)根本不会被调用。如果写:

then somefunc() would (probably) not be called at all. The same would be the case if one wrote:

SELECT somefunc() OR true;

情况也会一样。请注意,这与某些编程语言中布尔运算符的从左到右“短路”不同。

Note that this is not the same as the left-to-right “short-circuiting” of Boolean operators that is found in some programming languages.

因此,不应将带副作用的函数用作复杂表达式的一部分。特别不要依赖 WHEREHAVING 子句中的副作用或求值顺序,因为这些子句在制定执行计划时需要大量重新处理。那些子句中的布尔表达式(AND/OR/NOT 组合)可以按照布尔代数法则允许的任何方式重新组织。

As a consequence, it is unwise to use functions with side effects as part of complex expressions. It is particularly dangerous to rely on side effects or evaluation order in WHERE and HAVING clauses, since those clauses are extensively reprocessed as part of developing an execution plan. Boolean expressions (AND/OR/NOT combinations) in those clauses can be reorganized in any manner allowed by the laws of Boolean algebra.

当必须强制执行顺序时,可以使用 _CASE_结构(请参见 Section 9.18)。 例如,这是在 _WHERE_子句中尝试避免除以零的不可靠方法:

When it is essential to force evaluation order, a CASE construct (see Section 9.18) can be used. For example, this is an untrustworthy way of trying to avoid division by zero in a WHERE clause:

SELECT ... WHERE x > 0 AND y/x > 1.5;

但这是安全的:

But this is safe:

SELECT ... WHERE CASE WHEN x > 0 THEN y/x > 1.5 ELSE false END;

CASE 构造这样使用时会破坏优化尝试,所以只有在必要时才应这样做。(在这个特殊示例中,写 y > 1.5*x 替代会更好,以绕开问题。)

A CASE construct used in this fashion will defeat optimization attempts, so it should only be done when necessary. (In this particular example, it would be better to sidestep the problem by writing y > 1.5*x instead.)

但是,_CASE_并非对所有此类问题都是一劳永逸的解决办法。 上述技术的一个限制是,它不能防止过早评估常量子表达式。 如 Section 38.7 中所述,当规划查询而不是在执行查询时,可以评估标记为 _IMMUTABLE_的函数和运算符。 因此例如

CASE is not a cure-all for such issues, however. One limitation of the technique illustrated above is that it does not prevent early evaluation of constant subexpressions. As described in Section 38.7, functions and operators marked IMMUTABLE can be evaluated when the query is planned rather than when it is executed. Thus for example

SELECT CASE WHEN x > 0 THEN x ELSE 1/0 END FROM tab;

可能会导致除以零失败,因为计划器尝试简化常量子表达式,即使表中的每一行都 x > 0 使得 ELSE 臂决不会在运行时输入。

is likely to result in a division-by-zero failure due to the planner trying to simplify the constant subexpression, even if every row in the table has x > 0 so that the ELSE arm would never be entered at run time.

虽然那个具体示例可能看起来很傻,但显然不涉及常量的相关案例仍可能发生在函数内执行的查询中,因为函数参数和局部变量的值可以作为常量插入查询以用于规划目的。例如,在 PL/pgSQL 函数中,使用 IF-THEN-ELSE 语句来保护有风险的计算比将其嵌套在 CASE 表达式中安全得多。

While that particular example might seem silly, related cases that don’t obviously involve constants can occur in queries executed within functions, since the values of function arguments and local variables can be inserted into queries as constants for planning purposes. Within PL/pgSQL functions, for example, using an IF-THEN-ELSE statement to protect a risky computation is much safer than just nesting it in a CASE expression.

同类性质的另一个限制是 CASE 不能阻止评估其中包含的聚合表达式,因为聚合表达式是在 SELECT 列表或 HAVING 子句中的其他表达式被考虑之前计算的。例如,以下查询可能导致除以零错误,尽管看起来已经进行了保护:

Another limitation of the same kind is that a CASE cannot prevent evaluation of an aggregate expression contained within it, because aggregate expressions are computed before other expressions in a SELECT list or HAVING clause are considered. For example, the following query can cause a division-by-zero error despite seemingly having protected against it:

SELECT CASE WHEN min(employees) > 0
            THEN avg(expenses / employees)
       END
    FROM departments;

min()avg() 聚合在所有输入行上同时计算,因此如果任何行的 employees 等于零,则在有机会测试 min() 结果之前除以零错误将发生。相反,使用 WHEREFILTER 子句防止有问题的输入行在第一位到达聚合函数。

The min() and avg() aggregates are computed concurrently over all the input rows, so if any row has employees equal to zero, the division-by-zero error will occur before there is any opportunity to test the result of min(). Instead, use a WHERE or FILTER clause to prevent problematic input rows from reaching an aggregate function in the first place.