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

CREATE CAST

CREATE CAST — 定義一個新的型別轉換

概要

CREATE CAST (source_type AS target_type)
    WITH FUNCTION function_name [ (argument_type [, ...]) ]
    [ AS ASSIGNMENT | AS IMPLICIT ]

CREATE CAST (source_type AS target_type)
    WITHOUT FUNCTION
    [ AS ASSIGNMENT | AS IMPLICIT ]

CREATE CAST (source_type AS target_type)
    WITH INOUT
    [ AS ASSIGNMENT | AS IMPLICIT ]

描述

CREATE CAST 定義一個新的型別轉換。型別轉換指定了如何在兩種資料型別之間執行轉換。例如,

SELECT CAST(42 AS float8);

透過呼叫先前指定的函式(在此例中為 float8(int4))將整數常量 42 轉換為 float8 型別。(如果未定義合適的型別轉換,則轉換失敗。)

兩種型別可以二進位制可轉換,這意味著轉換可以“免費”執行,而無需呼叫任何函式。這要求對應的值使用相同的內部表示。例如,textvarchar 型別可以雙向二進位制可轉換。二進位制可轉換並非一定是對稱關係。例如,在當前實現中,從 xmltext 的轉換可以免費執行,但反方向需要一個至少執行語法檢查的函式。(雙向二進位制可轉換的兩種型別也稱為二進位制相容。)

您可以使用 WITH INOUT 語法將型別轉換定義為I/O 轉換型別轉換。I/O 轉換型別轉換透過呼叫源資料型別的輸出函式,並將生成的字串傳遞給目標資料型別的輸入函式來執行。在許多常見情況下,此功能避免了為轉換編寫單獨的轉換函式。I/O 轉換型別轉換的作用與常規基於函式的型別轉換相同;只有實現方式不同。

預設情況下,型別轉換隻能透過顯式型別轉換請求來呼叫,即顯式的 CAST(x AS typename)x::typename 構造。

如果型別轉換標記為 AS ASSIGNMENT,則在將值賦給目標資料型別的列時,可以隱式呼叫它。例如,假設 foo.f1 是一個 text 型別的列,那麼,

INSERT INTO foo (f1) VALUES (42);

如果從 integertext 的型別轉換標記為 AS ASSIGNMENT,則允許執行此操作,否則不允許。(我們通常使用賦值型別轉換這個術語來描述這種型別的轉換。)

如果型別轉換標記為 AS IMPLICIT,則可以在任何上下文中隱式呼叫它,無論是賦值還是表示式內部。(我們通常使用隱式型別轉換這個術語來描述這種型別的轉換。)例如,考慮以下查詢:

SELECT 2 + 4.0;

解析器最初將常量標記為 integernumeric 型別。系統目錄中沒有 integer + numeric 運算子,但有一個 numeric + numeric 運算子。因此,如果存在從 integernumeric 的型別轉換並且該型別轉換標記為 AS IMPLICIT — 實際上確實如此 — 則查詢將成功。解析器將應用隱式轉換,並像查詢寫成這樣一樣進行解析:

SELECT CAST ( 2 AS numeric ) + 4.0;

現在,目錄還提供了從 numericinteger 的型別轉換。如果該型別轉換被標記為 AS IMPLICIT — 它實際上並未被標記 — 那麼解析器將面臨在上述解釋和將 numeric 常量轉換為 integer 並應用 integer + integer 運算子之間的選擇。由於不知道偏好哪種選擇,它將放棄並宣告查詢模稜兩可。只有兩個型別轉換中的一個具有隱式轉換,這是我們教解析器如何偏好解析混合 numericinteger 表示式為 numeric 的方式;這方面沒有內建的知識。

謹慎地標記隱式型別轉換是明智的。過多的隱式型別轉換路徑可能導致 PostgreSQL 選擇令人驚訝的命令解釋,或者由於存在多種可能的解釋而無法解析命令。一個經驗法則是,只有在同一通用型別類別中的型別之間進行資訊保留轉換時,才使型別轉換能夠隱式呼叫。例如,從 int2int4 的型別轉換可以合理地是隱式的,但從 float8int4 的型別轉換可能應該是僅賦值的。跨型別類別的轉換,例如 textint4,最好只做顯式轉換。

注意

有時出於可用性或符合標準的原因,需要在型別集合之間提供多個隱式型別轉換,從而導致無法像上面那樣避免的歧義。解析器有一個基於型別類別首選型別的回退啟發式方法,這有助於在這些情況下提供所需的行為。有關更多資訊,請參閱 CREATE TYPE

要建立型別轉換,您必須擁有源資料型別或目標資料型別的所屬許可權,並且對另一個型別擁有 USAGE 許可權。要建立二進位制可轉換的型別轉換,您必須是超級使用者。(此限制是因為錯誤的二進位制可轉換轉換很容易導致伺服器崩潰。)

引數

source_type

型別轉換的源資料型別的名稱。

target_type

型別轉換的目標資料型別的名稱。

function_name[(argument_type [, ...])]

用於執行型別轉換的函式。函式名稱可以包含模式限定。如果未包含,則將在模式搜尋路徑中查詢該函式。函式的返回資料型別必須與型別轉換的目標型別匹配。其引數將在下面討論。如果未指定引數列表,則函式名稱在其模式中必須是唯一的。

WITHOUT FUNCTION

指示源型別可以二進位制可轉換為目標型別,因此無需函式即可執行型別轉換。

WITH INOUT

指示型別轉換是 I/O 轉換型別轉換,透過呼叫源資料型別的輸出函式,並將生成的字串傳遞給目標資料型別的輸入函式來執行。

AS ASSIGNMENT

指示型別轉換可以在賦值上下文中隱式呼叫。

AS IMPLICIT

指示型別轉換可以在任何上下文中隱式呼叫。

型別轉換實現函式可以有一個到三個引數。第一個引數型別必須與型別轉換的源型別相同或可以從源型別二進位制可轉換。第二個引數(如果存在)必須是 integer 型別;它接收與目標型別關聯的型別修飾符,如果沒有則為 -1。第三個引數(如果存在)必須是 boolean 型別;如果型別轉換是顯式型別轉換,則為 true,否則為 false。(SQL 標準要求在某些情況下顯式和隱式轉換具有不同的行為,這很奇怪。此引數是為必須實現此類轉換的函式提供的。不建議您設計自己的資料型別,使其具有這種意義。)

型別轉換函式的返回型別必須與型別轉換的目標型別相同或可以二進位制可轉換為目標型別。

通常,型別轉換必須具有不同的源資料型別和目標資料型別。但是,如果型別轉換有一個包含多個引數的實現函式,則允許宣告具有相同源和目標型別的型別轉換。這用於在系統目錄中表示型別特定的長度轉換函式。指定的函式用於將型別的值轉換為其第二個引數給出的型別修飾符值。

當型別轉換具有不同的源和目標型別以及一個接受多個引數的函式時,它支援在一個步驟中將一種型別轉換為另一種型別並應用長度轉換。當沒有此類條目可用時,轉換為使用型別修飾符的型別需要兩個型別轉換步驟,一個用於在資料型別之間進行轉換,第二個用於應用修飾符。

目前,轉換為域型別或從域型別轉換沒有效果。轉換為域或從域轉換使用與其基礎型別相關的型別轉換。

註釋

使用 DROP CAST 刪除使用者定義的型別轉換。

請記住,如果您想能夠雙向轉換型別,則需要顯式宣告雙向型別轉換。

通常不需要在使用者定義型別和標準字串型別(textvarcharchar(n),以及定義為字串類別的使用者定義型別)之間建立型別轉換。 PostgreSQL 會為這些型別提供自動 I/O 轉換型別轉換。自動轉換為字串型別的型別轉換被視為賦值型別轉換,而自動從字串型別轉換的型別轉換僅顯式。您可以透過宣告自己的型別轉換來替換自動型別轉換來覆蓋此行為,但通常唯一的原因是如果您希望轉換比標準的僅賦值或僅顯式設定更容易呼叫。另一個可能的原因是您希望轉換的行為與型別的 I/O 函式不同;但這足夠令人驚訝,您應該三思而後行。(一些內建型別確實在轉換方面具有不同的行為,主要是由於 SQL 標準的要求。)

雖然不是必需的,但建議您繼續遵循此舊慣例,即根據目標資料型別為型別轉換實現函式命名。許多使用者習慣於能夠使用函式風格的表示法轉換資料型別,即 typename(x)。此表示法實際上只是一個型別轉換實現函式的呼叫;它不被特別視為型別轉換。如果您的轉換函式不是按照此約定命名的,您將令使用者感到驚訝。由於 PostgreSQL 允許使用不同的引數型別過載相同的函式名稱,因此擁有來自不同型別但都使用目標型別名稱的多個轉換函式沒有任何困難。

注意

實際上,前一段過於簡化了:在兩種情況下,函式呼叫構造將被視為型別轉換請求,而無需將其與實際函式匹配。如果函式呼叫 name(x) 與任何現有函式都不完全匹配,但 name 是資料型別的名稱,並且 pg_cast 提供了從 x 的型別到該型別的二進位制可轉換型別轉換,則該呼叫將被解釋為二進位制可轉換型別轉換。此例外是為了使二進位制可轉換型別轉換能夠使用函式語法呼叫,即使它們沒有函式。同樣,如果不存在 pg_cast 條目,但型別轉換是到字串型別或從字串型別,則呼叫將被解釋為 I/O 轉換型別轉換。此例外允許使用函式語法呼叫 I/O 轉換型別轉換。

注意

還有一個例外中的例外:從複合型別到字串型別的 I/O 轉換型別轉換不能使用函式語法呼叫,但必須以顯式型別轉換語法(CAST:: 表示法)編寫。此例外被新增是因為在自動提供的 I/O 轉換型別轉換引入之後,當意圖是函式或列引用時,很容易意外地呼叫此類轉換。

示例

使用函式 int4(bigint) 建立從 bigint 型別到 int4 型別的賦值型別轉換:

CREATE CAST (bigint AS int4) WITH FUNCTION int4(bigint) AS ASSIGNMENT;

(此型別轉換已在系統中預定義。)

相容性

CREATE CAST 命令符合SQL標準,但 SQL 沒有為二進位制可轉換型別或實現函式的附加引數提供規定。 AS IMPLICIT 也是 PostgreSQL 的擴充套件。

提交更正

如果您在文件中看到任何不正確、不符合您對特定功能的經驗或需要進一步說明的內容,請使用 此表格 報告文件問題。