支援的版本:目前 (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

36.2. PostgreSQL 類型系統 #

PostgreSQL 資料類型可以分為基礎類型、容器類型、網域和偽類型。

36.2.1. 基礎類型 #

基礎類型是指像 integer 這樣的類型,它們是在 PostgreSQL 語言層級之下實現的SQL(通常是用 C 等低階語言)。它們通常對應於通常被稱為抽象資料類型的東西。PostgreSQL 只能透過使用者提供的函數來操作這些類型,並且僅在使用者描述的範圍內理解這些類型的行為。內建的基礎類型在第 8 章中描述。

列舉 (enum) 類型可以被認為是基礎類型的一個子類別。主要區別在於它們可以使用 PostgreSQL 指令創建,而無需任何低階程式設計。SQL命令,而無需任何低階程式設計。有關更多資訊,請參閱第 8.7 節

36.2.2. 容器類型 #

PostgreSQL 有三種 容器 類型,它們是包含其他類型多個值的類型。這些是陣列、複合類型和範圍。

陣列可以保存多個相同類型的值。會自動為每個基礎類型、複合類型、範圍類型和網域類型建立陣列類型。但是沒有陣列的陣列。就類型系統而言,多維陣列與一維陣列相同。有關更多資訊,請參閱第 8.15 節

每當使用者建立表時,就會建立複合類型或列類型。也可以使用 CREATE TYPE 來定義 獨立 複合類型,而沒有相關的表。複合類型只是一個具有關聯欄位名稱的類型列表。複合類型的值是欄位值的列或記錄。有關更多資訊,請參閱第 8.16 節

範圍類型可以保存相同類型的兩個值,它們是範圍的下限和上限。範圍類型是使用者創建的,儘管存在一些內建的範圍類型。有關更多資訊,請參閱第 8.17 節

36.2.3. 網域 #

網域基於特定的底層類型,並且在許多用途上可以與其底層類型互換。但是,網域可以具有約束,將其有效值限制為底層類型允許的子集。網域是使用SQL命令 CREATE DOMAIN 建立的。有關更多資訊,請參閱第 8.18 節

36.2.4. 偽類型 #

有一些 偽類型 用於特殊目的。偽類型不能顯示為表的列或容器類型的元件,但它們可以用於宣告函數的參數和結果類型。這在類型系統中提供了一種機制來識別函數的特殊類別。表 8.27 列出了現有的偽類型。

36.2.5. 多型類型 #

一些特別令人感興趣的偽類型是多型類型,它被用於宣告多型函數。這個強大的功能允許單個函數定義操作多種不同的資料類型,而具體的資料類型取決於特定呼叫中實際傳遞給它的資料類型。多型類型顯示在表 36.1中。它們的一些使用範例出現在第 36.5.11 節中。

表 36.1. 多型類型

名稱 族系 描述
anyelement 簡單 表示函數接受任何資料類型
anyarray 簡單 表示函數接受任何陣列資料類型
anynonarray 簡單 表示函數接受任何非陣列資料類型
anyenum 簡單 表示函數接受任何列舉資料類型(參見第 8.7 節
anyrange 簡單 表示函數接受任何範圍資料類型(參見第 8.17 節
anymultirange 簡單 表示函數接受任何多重範圍資料類型(參見第 8.17 節
anycompatible 通用 表示函數接受任何資料類型,並將多個引數自動提升為通用資料類型
anycompatiblearray 通用 表示函數接受任何陣列資料類型,並將多個引數自動提升為通用資料類型
anycompatiblenonarray 通用 表示函數接受任何非陣列資料類型,並將多個引數自動提升為通用資料類型
anycompatiblerange 通用 表示函數接受任何範圍資料類型,並將多個引數自動提升為通用資料類型
anycompatiblemultirange 通用 表示函數接受任何多重範圍資料類型,並將多個引數自動提升為通用資料類型

多型引數和結果相互關聯,並在解析呼叫多型函數的查詢時解析為特定的資料類型。當有多個多型引數時,輸入值的實際資料類型必須如下述匹配。如果函數的結果類型是多型的,或者它具有多型類型的輸出參數,則這些結果的類型將從多型輸入的實際類型中推斷出來,如下所述。

對於簡單族系的多型類型,匹配和推斷規則如下所示

宣告為anyelement的每個位置(引數或傳回值)都可以具有任何特定的實際資料類型,但在任何給定的呼叫中,它們必須全部是相同的實際類型。宣告為anyarray的每個位置都可以具有任何陣列資料類型,但類似地,它們必須全部是相同的類型。同樣地,宣告為anyrange的位置必須全部是相同的範圍類型。對於anymultirange也是如此。

此外,如果存在宣告為anyarray的位置和宣告為anyelement的其他位置,則anyarray位置中的實際陣列類型必須是一個陣列,該陣列的元素是出現在anyelement位置中的相同類型。anynonarray的處理方式與anyelement完全相同,但增加了實際類型不能是陣列類型的額外約束。anyenum的處理方式與anyelement完全相同,但增加了實際類型必須是列舉類型的額外約束。

同樣地,如果存在宣告為anyrange的位置和宣告為anyelementanyarray的其他位置,則anyrange位置中的實際範圍類型必須是一個範圍,該範圍的子類型與出現在anyelement位置中的類型相同,並且與anyarray位置的元素類型相同。如果存在宣告為anymultirange的位置,則它們的實際多重範圍類型必須包含與宣告為anyrange的參數匹配的範圍,以及與宣告為anyelementanyarray的參數匹配的基礎元素。

因此,當使用多型類型宣告多個引數位置時,最終的結果是僅允許某些實際引數類型的組合。例如,宣告為equal(anyelement, anyelement)的函數將接受任何兩個輸入值,只要它們是相同的資料類型即可。

當函數的傳回值宣告為多型類型時,必須至少有一個也是多型的引數位置,並且為多型引數提供的實際資料類型決定了該呼叫的實際結果類型。例如,如果還沒有陣列下標機制,則可以定義一個函數,將下標實現為subscript(anyarray, integer) returns anyelement。此宣告將實際的第一個引數限制為陣列類型,並允許解析器從實際的第一個引數的類型推斷出正確的結果類型。另一個範例是宣告為f(anyarray) returns anyenum的函數僅接受列舉類型的陣列。

在大多數情況下,解析器可以從同一族系中不同多型類型的引數推斷出多型結果類型的實際資料類型;例如,可以從anyelement推斷出anyarray,反之亦然。一個例外是anyrange類型的多型結果需要anyrange類型的引數;它無法從anyarrayanyelement引數推斷出來。這是因為可能存在多個具有相同子類型的範圍類型。

請注意,anynonarrayanyenum不代表單獨的類型變數;它們與anyelement的類型相同,只是具有額外的約束。例如,將函數宣告為f(anyelement, anyenum)等效於將其宣告為f(anyenum, anyenum):兩個實際引數都必須是相同的列舉類型。

對於多型別的 common 家族而言,其匹配和推導規則大致上與 simple 家族相同,但有一個主要差異:引數的實際型別不需要完全相同,只要它們可以隱式轉換為單一的通用型別即可。通用型別的選擇遵循與 UNION 及相關結構相同的規則(請參閱第 10.5 節)。通用型別的選擇會考量 anycompatibleanycompatiblenonarray 輸入的實際型別、anycompatiblearray 輸入的陣列元素型別、anycompatiblerange 輸入的範圍子型別,以及 anycompatiblemultirange 輸入的多重範圍子型別。如果存在 anycompatiblenonarray,則通用型別必須是非陣列型別。一旦識別出通用型別,anycompatibleanycompatiblenonarray 位置中的引數會自動轉換為該型別,而 anycompatiblearray 位置中的引數會自動轉換為該型別的陣列型別。

由於無法僅根據子型別選擇範圍型別,因此使用 anycompatiblerange 和/或 anycompatiblemultirange 要求所有宣告為該型別的引數都具有相同的實際範圍和/或多重範圍型別,並且該型別的子型別與選定的通用型別一致,因此不需要轉換範圍值。與 anyrangeanymultirange 相同,將 anycompatiblerangeanymultirange 用作函數結果型別,需要存在 anycompatiblerangeanycompatiblemultirange 引數。

請注意,沒有 anycompatibleenum 型別。此類型別不會非常有用,因為通常沒有任何隱式轉換為列舉型別,這表示無法解析不同列舉輸入的通用型別。

simplecommon 多型別家族代表兩組獨立的型別變數。例如,考慮

CREATE FUNCTION myfunc(a anyelement, b anyelement,
                       c anycompatible, d anycompatible)
RETURNS anycompatible AS ...

在實際呼叫此函數時,前兩個輸入必須具有完全相同的型別。後兩個輸入必須可升級為通用型別,但此型別不必與前兩個輸入的型別有任何關係。結果將具有後兩個輸入的通用型別。

可變參數函數(接受可變數量的引數,如第 36.5.6 節所述)可以是多型的:這可以透過將其最後一個參數宣告為 VARIADIC anyarrayVARIADIC anycompatiblearray 來完成。為了進行引數匹配和確定實際的結果型別,此類函數的行為與您編寫適當數量的 anynonarrayanycompatiblenonarray 參數相同。

提交更正

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