Redrock Postgres 搜索 英文
版本: 9.3 / 9.4 / 9.5 / 9.6 / 10 / 11 / 12 / 13 / 14 / 15 / 16 / 17

10.5. UNIONCASE及相关构造 #

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

针对 UNIONCASE 和相关构造的类型解析

  1. 如果所有输入都属于同一类型,且该类型不是 unknown,则按该类型解析。

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

  3. 如果所有输入都属于 unknown 类型,则按类型 text 解析(字符串类别的首选类型)。否则,在使用剩余规则时会忽略 unknown 输入。

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

  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子句。在其他所有情况下,从左到右表示表达式在查询文本中出现的顺序。