CREATE CAST — 定義新的轉換 (cast)
CREATE CAST (source_type
AStarget_type
) WITH FUNCTIONfunction_name
[ (argument_type
[, ...]) ] [ AS ASSIGNMENT | AS IMPLICIT ] CREATE CAST (source_type
AStarget_type
) WITHOUT FUNCTION [ AS ASSIGNMENT | AS IMPLICIT ] CREATE CAST (source_type
AStarget_type
) WITH INOUT [ AS ASSIGNMENT | AS IMPLICIT ]
CREATE CAST
定義一個新的轉換 (cast)。一個轉換指定如何在兩種資料類型之間執行轉換。例如:
SELECT CAST(42 AS float8);
通過調用先前指定的函數(在本例中為 float8(int4)
)將整數常數 42 轉換為 float8
類型。(如果沒有定義合適的轉換,轉換將失敗。)
兩種類型可以是二進制強制類型轉換 (binary coercible),這意味著可以在不調用任何函數的情況下“免費”執行轉換。 這要求相應的值使用相同的內部表示形式。 例如,text
和 varchar
類型在兩個方向上都是二進制強制類型轉換。 二進制強制類型轉換不一定是對稱關係。 例如,從 xml
到 text
的轉換可以在當前的實現中免費執行,但反方向需要一個至少執行語法檢查的函數。 (雙向二進制強制類型轉換的兩種類型也稱為二進制相容。)
您可以使用 WITH INOUT
語法將轉換定義為I/O 轉換 (I/O conversion cast)。 I/O 轉換是通過調用源資料類型的輸出函數,然後將結果字串傳遞給目標資料類型的輸入函數來執行的。 在許多常見情況下,此功能避免了為轉換編寫單獨的轉換函數的需要。 I/O 轉換的作用與常規的基於函數的轉換相同; 只是實現方式不同。
默認情況下,只能通過顯式轉換請求來調用轉換,即顯式的 CAST(
或 x
AS typename
)x
::
typename
構造。
如果轉換標記為 AS ASSIGNMENT
,則在將值賦給目標資料類型的列時可以隱式調用它。 例如,假設 foo.f1
是 text
類型的列,那麼
INSERT INTO foo (f1) VALUES (42);
如果從 integer
類型到 text
類型的轉換標記為 AS ASSIGNMENT
,則允許該操作,否則不允許。 (我們通常使用術語賦值轉換 (assignment cast)來描述這種轉換。)
如果轉換標記為 AS IMPLICIT
,則可以在任何上下文中隱式調用它,無論是賦值還是內部表達式中。 (我們通常使用術語隱式轉換 (implicit cast)來描述這種轉換。) 例如,考慮以下查詢:
SELECT 2 + 4.0;
解析器最初將常數標記為 integer
和 numeric
類型。 系統目錄中沒有 integer
+
numeric
運算符,但有一個 numeric
+
numeric
運算符。 因此,如果從 integer
到 numeric
的轉換可用並且標記為 AS IMPLICIT
,則查詢將成功 — 事實上它是。 解析器將應用隱式轉換並解析查詢,就像它被寫成
SELECT CAST ( 2 AS numeric ) + 4.0;
現在,目錄也提供從 numeric
到 integer
的轉換。 如果該轉換被標記為 AS IMPLICIT
— 事實上它不是 — 則解析器將面臨在上述解釋和將 numeric
常數轉換為 integer
並應用 integer
+
integer
運算符的替代方案之間進行選擇。 由於缺乏任何關於更喜歡哪個選擇的知識,它會放棄並宣布查詢不明確。 只有兩個轉換中的一個是隱式的,這就是我們教導解析器首選將混合的 numeric
-和-integer
表達式解析為 numeric
的方式; 沒有關於此的內置知識。
明智的做法是對將轉換標記為隱式轉換持保守態度。 過多的隱式轉換路徑可能會導致 PostgreSQL 選擇令人驚訝的命令解釋,或者由於存在多種可能的解釋而無法解析命令。 一個好的經驗法則是僅對同一通用類型類別中類型之間的信息保留轉換進行隱式調用。 例如,從 int2
到 int4
的轉換可以合理地是隱式的,但從 float8
到 int4
的轉換可能應該僅是賦值轉換。 跨類型類別的轉換,例如 text
到 int4
,最好僅進行顯式轉換。
有時,由於可用性或標準合規性原因,需要在類型集中提供多個隱式轉換,從而導致無法像上面那樣避免的歧義。 解析器具有基於類型類別 (type categories)和首選類型 (preferred types)的回退式啟發法,可以幫助在這種情況下提供所需的行為。 有關更多信息,請參閱CREATE TYPE。
要創建轉換,您必須擁有源或目標資料類型,並擁有另一種類型的 USAGE
權限。 要創建二進制強制類型轉換,您必須是超級用戶。 (之所以進行此限制,是因為錯誤的二進制強制類型轉換很容易導致伺服器崩潰。)
source_type
轉換的源資料類型的名稱。
target_type
轉換的目標資料類型的名稱。
function_name
[(argument_type
[, ...])]
用來執行轉換的函式。函式名稱可以使用 schema 限定詞。如果沒有,將會在 schema 搜尋路徑中尋找該函式。函式的結果資料類型必須符合轉換的目標類型。其引數將在下面討論。如果未指定引數列表,則函式名稱在其 schema 中必須是唯一的。
WITHOUT FUNCTION
表示來源類型可以二進位相容於目標類型,因此不需要函式來執行轉換。
WITH INOUT
表示該轉換是 I/O 轉換,透過調用來源資料類型的輸出函式,並將產生的字串傳遞給目標資料類型的輸入函式來執行。
AS ASSIGNMENT
表示可以在賦值上下文中隱式調用該轉換。
AS IMPLICIT
表示可以在任何上下文中隱式調用該轉換。
轉換實作函式可以有一個到三個引數。第一個引數類型必須與轉換的來源類型相同或可進行二進位相容轉換。第二個引數(如果存在)必須是 integer
類型;它接收與目標類型相關聯的類型修飾符,如果沒有,則為 -1
。第三個引數(如果存在)必須是 boolean
類型;如果轉換是顯式轉換,則接收 true
,否則接收 false
。(奇怪的是,SQL 標準要求在某些情況下顯式和隱式轉換有不同的行為。提供此引數是為了給必須實作此類轉換的函式使用。不建議您設計自己的資料類型,使得這個引數變得重要。)
轉換函式的返回類型必須與轉換的目標類型相同或可進行二進位相容轉換。
通常,轉換必須具有不同的來源和目標資料類型。但是,如果轉換具有多個引數的轉換實作函式,則允許宣告具有相同來源和目標類型的轉換。這用於表示系統目錄中特定於類型的長度強制轉換函式。指定的函式用於將該類型的值強制轉換為其第二個引數給出的類型修飾符值。
當轉換具有不同的來源和目標類型,並且具有一個接收多個引數的函式時,它支援從一種類型轉換為另一種類型,並在單一步驟中應用長度強制轉換。如果沒有此類條目可用,則強制轉換為使用類型修飾符的類型涉及兩個轉換步驟,一個是在資料類型之間進行轉換,另一個是應用修飾符。
目前,轉換為或從網域類型轉換沒有任何效果。轉換為或從網域類型會使用與其底層類型相關聯的轉換。
使用 DROP CAST
來移除使用者定義的轉換。
請記住,如果您希望能夠以兩種方式轉換類型,則需要顯式地宣告這兩種方式的轉換。
通常不需要在使用者定義類型和標準字串類型(text
、varchar
和 char(
,以及定義為字串類別的使用者定義類型)之間建立轉換。PostgreSQL 針對此情況提供自動 I/O 轉換。自動轉換為字串類型被視為賦值轉換,而從字串類型自動轉換僅限於顯式轉換。您可以宣告自己的轉換來取代自動轉換,以覆蓋此行為,但通常唯一的原因是您希望該轉換比標準的僅限賦值或僅限顯式轉換更容易調用。另一個可能的原因是您希望轉換的行為與該類型的 I/O 函式不同;但這足以令人驚訝,您應該三思而後行,看看這是否是一個好主意。(少數內建類型確實對轉換有不同的行為,主要是由於 SQL 標準的要求。)n
)
雖然不是必需的,但建議您繼續遵循這個舊的慣例,以目標資料類型命名轉換實作函式。許多使用者習慣於能夠使用函式式表示法來轉換資料類型,也就是 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 擴充功能。
如果您在文件中發現任何不正確的地方、與您使用特定功能的經驗不符或需要進一步說明,請使用此表單來報告文件問題。