2025年9月25日: PostgreSQL 18 釋出!
支援版本: 當前 (18) / 17 / 16 / 15 / 14 / 13
開發版本: devel
不支援版本: 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. UNION, CASE, 以及相關構造 #

SQL UNION 構造必須將可能不相同的型別匹配起來,才能成為一個單一的結果集。匹配演算法會單獨應用於 union 查詢的每個輸出列。 INTERSECTEXCEPT 構造以與 UNION 相同的方式匹配不相同的型別。其他一些構造,包括 CASE, ARRAY, VALUES, 以及 GREATESTLEAST 函式,使用相同的演算法來匹配它們的組成表示式並選擇一個結果資料型別。

UNION, CASE, 以及相關構造的型別匹配

  1. 如果所有輸入都屬於同一型別,並且不是 unknown,則匹配為該型別。

  2. 如果任何輸入是域型別,則在所有後續步驟中將其視為域的基本型別。[12]

  3. 如果所有輸入都是 unknown 型別,則匹配為 text 型別(字串類別的首選型別)。否則,為進行剩餘規則的匹配,將忽略 unknown 輸入。

  4. 如果非 unknown 輸入的型別類別不全相同,則失敗。

  5. 選擇第一個非 unknown 輸入型別作為候選型別,然後按從左到右的順序考慮每個其他非 unknown 輸入型別。[13] 如果候選型別可以隱式轉換為其他型別,但反之不行,則選擇其他型別作為新的候選型別。然後繼續考慮剩餘的輸入。如果在任何階段都選擇了首選型別,則停止考慮其他輸入。

  6. 將所有輸入轉換為最終候選型別。如果給定輸入型別沒有到候選型別的隱式轉換,則失敗。

以下是一些示例。

示例 10.10. Union 中帶有未明確指定型別的型別匹配

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

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

此處,未知型別字面量 'b' 將被解析為 text 型別。


示例 10.11. 簡單 Union 中的型別匹配

SELECT 1.2 AS "numeric" UNION SELECT 1;

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

字面量 1.2 的型別是 numeric,並且 integer1 可以隱式轉換為 numeric,因此使用了該型別。


示例 10.12. 轉置 Union 中的型別匹配

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

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

此處,由於 real 型別不能隱式轉換為 integer,但 integer 可以隱式轉換為 real,因此 Union 的結果型別被解析為 real


示例 10.13. 巢狀 Union 中的型別匹配

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 子句。在所有其他情況下,“從左到右”是指表示式在查詢文字中出現的順序。

提交更正

如果您在文件中發現任何不正確、與您對特定功能的體驗不符或需要進一步澄清的內容,請使用此表單來報告文件問題。