2024年9月26日: PostgreSQL 17 发布!
支持版本:当前 (17) / 16 / 15 / 14 / 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

10.5. UNIONCASE 和相关构造 #

SQL UNION 构造必须将可能不同的类型匹配起来,才能形成单个结果集。该解析算法分别应用于联合查询的每个输出列。INTERSECTEXCEPT 构造以与 UNION 相同的方式解析不同的类型。其他一些构造,包括 CASEARRAYVALUES 以及 GREATESTLEAST 函数,使用相同的算法来匹配其组件表达式并选择结果数据类型。

UNIONCASE 和相关构造的类型解析

  1. 如果所有输入都是相同类型,并且它不是 unknown,则解析为该类型。

  2. 如果任何输入是域类型,则在后续所有步骤中将其视为域的基本类型。[12]

  3. 如果所有输入都是 unknown 类型,则解析为 text 类型(字符串类别的首选类型)。否则,在其余规则中将忽略 unknown 输入。

  4. 如果非 unknown 输入并非全部属于同一类型类别,则失败。

  5. 选择第一个非 unknown 输入类型作为候选类型,然后从左到右考虑每个其他非 unknown 输入类型。[13]如果候选类型可以隐式转换为其他类型,但反之则不行,则选择其他类型作为新的候选类型。然后继续考虑剩余的输入。如果在此过程的任何阶段选择了首选类型,则停止考虑其他输入。

  6. 将所有输入转换为最终候选类型。如果从给定输入类型到候选类型没有隐式转换,则失败。

以下是一些示例。

示例 10.10. 联合中类型未指定时的类型解析

SELECT text 'a' AS "text" UNION SELECT 'b';

 text
------
 a
 b
(2 rows)

在这里,unknown 类型字面量 'b' 将被解析为 text 类型。


示例 10.11. 简单联合中的类型解析

SELECT 1.2 AS "numeric" UNION SELECT 1;

 numeric
---------
       1
     1.2
(2 rows)

字面量 1.2 的类型为 numeric,而 integer1 可以隐式转换为 numeric,因此使用该类型。


示例 10.12. 转置联合中的类型解析

SELECT 1 AS "real" UNION SELECT CAST('2.2' AS REAL);

 real
------
    1
  2.2
(2 rows)

在这里,由于 real 类型不能隐式转换为 integer 类型,但 integer 类型可以隐式转换为 real 类型,因此联合结果类型被解析为 real 类型。


示例 10.13. 嵌套联合中的类型解析

SELECT NULL UNION SELECT NULL UNION SELECT 1;

ERROR:  UNION types text and integer cannot be matched

此错误发生是因为 PostgreSQL 将多个 UNION 视为成对操作的嵌套;也就是说,此输入与以下内容相同

(SELECT NULL UNION SELECT NULL) UNION SELECT 1;

根据上面给出的规则,内部 UNION 被解析为发出 text 类型。然后,外部 UNION 的输入类型为 textinteger,从而导致观察到的错误。可以通过确保最左边的 UNION 至少有一个所需结果类型的输入来解决此问题。

INTERSECTEXCEPT 操作也以类似的方式成对解析。但是,本节中描述的其他构造在其一个解析步骤中考虑所有输入。




[12] 与运算符和函数的域输入处理方式类似,此行为允许在 UNION 或类似构造中保留域类型,只要用户小心确保所有输入都隐式或显式地具有完全相同的类型即可。否则将使用域的基本类型。

[13] 由于历史原因,CASE 将其 ELSE 子句(如果有)视为 第一个 输入,然后考虑 THEN 子句。在所有其他情况下,“从左到右”表示表达式在查询文本中出现的顺序。

提交更正

如果您在文档中发现任何不正确的内容,与您对特定功能的体验不符,或者需要进一步说明,请使用 此表单 报告文档问题。