W3Cschool
恭喜您成為首批注冊(cè)用戶
獲得88經(jīng)驗(yàn)值獎(jiǎng)勵(lì)
CREATE 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
定義一種新的造型。 一種造型指定如何在兩種數(shù)據(jù)類(lèi)型之間執(zhí)行轉(zhuǎn)換。例如,
SELECT CAST(42 AS float8);
通過(guò)調(diào)用一個(gè)之前指定的函數(shù)(這種情況中是 float8(int4)
)把整型常量 42 轉(zhuǎn)換成類(lèi)型 float8
(如果沒(méi)有定義合適的造型, 該轉(zhuǎn)換會(huì)失?。?。
兩種類(lèi)型可以是二進(jìn)制可強(qiáng)制,這表示該轉(zhuǎn)換 可以被“免費(fèi)”執(zhí)行而不用調(diào)用任何函數(shù)。這要求相應(yīng)的 值使用同樣的內(nèi)部表示。例如,類(lèi)型text
和 varchar
在雙向都是二進(jìn)制可強(qiáng)制的。二進(jìn)制可強(qiáng)制性并 不必是一種對(duì)稱(chēng)關(guān)系。例如,在當(dāng)前實(shí)現(xiàn)中從
xml
到 text
的造型可以被免費(fèi)執(zhí)行,但是反向則需要一個(gè)函數(shù)來(lái) 執(zhí)行至少一次語(yǔ)法檢查(兩種在雙向都二進(jìn)制值兼容的類(lèi)型也被稱(chēng)作二進(jìn) 制兼容)。
通過(guò)使用WITH INOUT
語(yǔ)法,你可以把一種造型定義 成I/O 轉(zhuǎn)換造型。一種 I/O 轉(zhuǎn)換造型執(zhí)行時(shí),會(huì)調(diào)用源 數(shù)據(jù)類(lèi)型的輸出函數(shù),并且把結(jié)果字符串傳遞給目標(biāo)數(shù)據(jù)類(lèi)型的輸入函數(shù)。 在很多常見(jiàn)情況中,這種特性避免了為轉(zhuǎn)換單獨(dú)定義一個(gè)造型函數(shù)。一種 I/O 轉(zhuǎn)換造型表現(xiàn)得和一個(gè)常規(guī)的基于函數(shù)的造型相同,只是實(shí)現(xiàn)不同而已。
默認(rèn)情況下,只有一次顯式造型請(qǐng)求才會(huì)調(diào)用造型, 形式是CAST(
or x
AS typename
)x
::
typename
。
如果造型被標(biāo)記為AS ASSIGNMENT
,那么在為一個(gè)目標(biāo)數(shù)據(jù) 類(lèi)型的列賦值時(shí)會(huì)隱式地調(diào)用它。例如,假設(shè)foo.f1
是 一個(gè)類(lèi)型text
的列,那么如果從類(lèi)型integer
到類(lèi)型text
的造型被標(biāo)記為AS ASSIGNMENT
,
則:
INSERT INTO foo (f1) VALUES (42);
將被允許,否則不會(huì)允許(我們通常使用賦值造型 來(lái)描述此類(lèi)造型)。
如果造型被標(biāo)記為AS IMPLICIT
,那么可以在任何上下文 中隱式地調(diào)用它,無(wú)論是賦值還是在一個(gè)表達(dá)式內(nèi)部(我們通常用術(shù)語(yǔ) 隱式造型來(lái)描述這類(lèi)造型)。例如,考慮這個(gè) 查詢:
SELECT 2 + 4.0;
解析器初始會(huì)把常量分別標(biāo)記為類(lèi)型integer
和 numeric
。在系統(tǒng)目錄中沒(méi)有integer
+
numeric
操作符,但是有一個(gè) numeric
+
numeric
操作符。 因此,如果有一種可用的從integer
到 numeric
的造型且被標(biāo)記為AS IMPLICIT
— 實(shí)際上確實(shí)有 — 該查詢將會(huì)成功。解析器將應(yīng)用該隱式造型 并且解決該查詢,就好像它被寫(xiě)成:
SELECT CAST ( 2 AS numeric ) + 4.0;
現(xiàn)在,系統(tǒng)目錄也提供一種從numeric
到integer
的造型。如果這種造型被標(biāo)記為AS IMPLICIT
— 實(shí)際上并沒(méi)有 — 那么解析器將面臨選擇:是用前面介紹的過(guò)程, 還是把numeric
常量造型成integer
并且應(yīng)用
integer
+
integer
操作符。由于 缺少哪種選擇更好的知識(shí),解析器會(huì)放棄并且說(shuō)明查詢有歧義。我們能 告訴解析器把一個(gè)混合了numeric
和integer
的 表達(dá)式解析成numeric
更好的方法就是只讓這兩種造型中的
一個(gè)是隱式的,沒(méi)有有關(guān)于此的內(nèi)建知識(shí)。
對(duì)標(biāo)記造型為隱式持保守態(tài)度是明智的。過(guò)多的隱式造型路徑可能導(dǎo)致 PostgreSQL以令人吃驚的方式解 釋命令,或者由于有多種可能解釋而根本無(wú)法解析命令。一種好的經(jīng)驗(yàn) 是讓一種造型只對(duì)于同一種一般類(lèi)型分類(lèi)中的類(lèi)型間的信息保持轉(zhuǎn)換隱式 可調(diào)用。例如,從int2
到int4
的造型 可以被合理地標(biāo)記為隱式,但是從float8
到
int4
的造型可能應(yīng)該只能在賦值時(shí)使用??珙?lèi)型分類(lèi) 的造型(如text
到int4
)最好只被用于顯式使用。
有時(shí)為了可用性或者標(biāo)準(zhǔn)兼容的原因,有必要提供在一個(gè)類(lèi)型集合之間 的多種隱式造型,這會(huì)導(dǎo)致上述不可避免的歧義。解析器還有一招基于 類(lèi)型分類(lèi)和優(yōu)先類(lèi)型的后手,它能幫助 提供這類(lèi)情況下預(yù)期的行為。詳見(jiàn) CREATE TYPE。
要?jiǎng)?chuàng)建一種造型,你必須擁有源數(shù)據(jù)類(lèi)型和目標(biāo)數(shù)據(jù)類(lèi)型并且具有在其他類(lèi)型上 的USAGE
特權(quán)。要?jiǎng)?chuàng)建一種二進(jìn)制可強(qiáng)制造型,你必須是一 個(gè)超級(jí)用戶(這種限制是因?yàn)殄e(cuò)誤的二進(jìn)制可強(qiáng)制造型轉(zhuǎn)換很容易讓服務(wù)器崩潰)。
source_type
該造型的源數(shù)據(jù)類(lèi)型的名稱(chēng)。
target_type
該造型的目標(biāo)數(shù)據(jù)類(lèi)型的名稱(chēng)。
function_name
[(argument_type
[, ...])]
被用于執(zhí)行該造型的函數(shù)。函數(shù)名稱(chēng)可以用模式限定。如果沒(méi)有被限定, 將在模式搜索路徑中查找該函數(shù)。函數(shù)的結(jié)果數(shù)據(jù)類(lèi)型必須是該造型的 目標(biāo)數(shù)據(jù)類(lèi)型。它的參數(shù)討論如下。 如果沒(méi)有指定參數(shù)列表,則該函數(shù)名稱(chēng)在其模式中必須是唯一的。
WITHOUT FUNCTION
指示源類(lèi)型可以二進(jìn)制強(qiáng)制到目標(biāo)類(lèi)型,因此執(zhí)行該造型不需要函數(shù)。
WITH INOUT
指示該造型是一種 I/O 轉(zhuǎn)換造型,執(zhí)行需要調(diào)用源數(shù)據(jù)類(lèi)型的輸出函數(shù), 并且把結(jié)果字符串傳遞給目標(biāo)數(shù)據(jù)類(lèi)型的輸入函數(shù)。
AS ASSIGNMENT
指示該造型可以在賦值的情況下被隱式調(diào)用。
AS IMPLICIT
指示該造型可以在任何上下文中被隱式調(diào)用。
造型實(shí)現(xiàn)函數(shù)可以具有 1 到 3 個(gè)參數(shù)。第一個(gè)參數(shù)類(lèi)型必須等于源類(lèi)型或者 能從源類(lèi)型二進(jìn)制強(qiáng)制得到。第二個(gè)參數(shù)(如果存在)必須是類(lèi)型 integer
,它接收與目標(biāo)類(lèi)型相關(guān)聯(lián)的類(lèi)型修飾符,如果沒(méi)有類(lèi)型 修飾符,它會(huì)收到-1
。第三個(gè)參數(shù)(如果存在)必須是類(lèi)型 boolean
,如果該造型是一種顯式造型,它會(huì)收到 true
,否則會(huì)收到
false
(奇怪地是,SQL 標(biāo)準(zhǔn)在 某些情況中對(duì)顯式和隱式造型要求不同的行為。這個(gè)參數(shù)被提供給必須實(shí)現(xiàn)這 類(lèi)造型的函數(shù)。不推薦在設(shè)計(jì)自己的數(shù)據(jù)類(lèi)型時(shí)用它)。
一個(gè)造型函數(shù)的返回類(lèi)型必須等于目標(biāo)類(lèi)型或者能二進(jìn)制強(qiáng)制到目標(biāo)類(lèi)型。
通常,強(qiáng)制轉(zhuǎn)換必須具有不同的源和目標(biāo)數(shù)據(jù)類(lèi)型。但是,如果它有一個(gè)帶有多個(gè)參數(shù)的強(qiáng)制轉(zhuǎn)換實(shí)現(xiàn)函數(shù),則可以聲明具有相同源類(lèi)型和目標(biāo)類(lèi)型的造型。它用于表示系統(tǒng)目錄中特定類(lèi)型的長(zhǎng)度強(qiáng)制函數(shù)。命名函數(shù)用于將類(lèi)型的值強(qiáng)制轉(zhuǎn)為其第二個(gè)參數(shù)提供的類(lèi)型修飾符的值。
當(dāng)強(qiáng)制轉(zhuǎn)換具有不同的源類(lèi)型和目標(biāo)類(lèi)型,并且一個(gè)函數(shù)使用多個(gè)參數(shù)時(shí),它支持從一種類(lèi)型轉(zhuǎn)換為另一種類(lèi)型,并在單個(gè)步驟中應(yīng)用長(zhǎng)度強(qiáng)制。如果沒(méi)有這樣的條目,強(qiáng)制轉(zhuǎn)換為使用類(lèi)型修飾符的類(lèi)型將涉及兩個(gè)強(qiáng)制轉(zhuǎn)換步驟,一個(gè)是在數(shù)據(jù)類(lèi)型之間進(jìn)行轉(zhuǎn)換,另一個(gè)是應(yīng)用修飾符。
向域類(lèi)型強(qiáng)制轉(zhuǎn)換或從域類(lèi)型強(qiáng)制轉(zhuǎn)換當(dāng)前無(wú)效。向域或從域強(qiáng)制轉(zhuǎn)換使用與其基礎(chǔ)類(lèi)型關(guān)聯(lián)的造型。
使用DROP CAST移除用戶定義的造型。
記住如果你想要能夠雙向轉(zhuǎn)換類(lèi)型,你需要在兩個(gè)方向上都 顯式聲明造型。
通常沒(méi)有必要?jiǎng)?chuàng)建用戶定義類(lèi)型和標(biāo)準(zhǔn)字符串類(lèi)型(text
、 varchar
和char(
, 以及被定義在字符串分類(lèi)中的用戶定義類(lèi)型)之間的造型。 PostgreSQL會(huì)為它們提供自動(dòng)的 I/O 轉(zhuǎn)換造型。 到字符串類(lèi)型的自動(dòng)造型被當(dāng)做賦值造型,而字符串類(lèi)型作為源的自動(dòng) 造型只能是顯式的。通過(guò)聲明你自己的造型來(lái)替換自動(dòng)造型可以覆蓋這 種行為,但是這樣做的唯一原因是你想讓該轉(zhuǎn)換比標(biāo)準(zhǔn)的設(shè)置更容易被 調(diào)用。另一種可能的原因是你想讓該轉(zhuǎn)換的行為與該類(lèi)型的 I/O 函數(shù)不 同,但這種原因足夠令人感到意外,你應(yīng)該考慮再三它是不是個(gè)好主意
(確實(shí)有少量?jī)?nèi)建類(lèi)型對(duì)轉(zhuǎn)換具有不同的行為,絕大部分是因?yàn)?SQL 標(biāo)準(zhǔn)的要求)。n
)
雖然不必要,推薦你繼續(xù)遵循這種在目標(biāo)數(shù)據(jù)類(lèi)型后面命名造型 實(shí)現(xiàn)函數(shù)的習(xí)慣。很多用戶習(xí)慣于能夠使用一種函數(shù)風(fēng)格的記法來(lái)造型 數(shù)據(jù)類(lèi)型,即typename
(x
)。 這種記法正好是對(duì)造型實(shí)現(xiàn)函數(shù)的調(diào)用,這里它沒(méi)有被作為造型特殊對(duì)待。 如果你的轉(zhuǎn)換函數(shù)沒(méi)有被指定支持這種習(xí)慣,那么你的用戶會(huì)覺(jué)得意外。 由于PostgreSQL允許用不同的參數(shù)類(lèi)型重載同一個(gè)
函數(shù)名,因此存在多個(gè)從不同類(lèi)型到同一目標(biāo)類(lèi)型的同名轉(zhuǎn)換函數(shù)并不困難。
實(shí)際上前一段過(guò)于簡(jiǎn)化了:有兩種情況中一個(gè)函數(shù)調(diào)用結(jié)構(gòu)在沒(méi)有被匹配到 一個(gè)實(shí)際函數(shù)時(shí)將被當(dāng)作一次造型請(qǐng)求。如果函數(shù)調(diào)用 name
(x
)沒(méi)有正好匹配任何現(xiàn)有函數(shù), 但name
是一種數(shù)據(jù)類(lèi)型的名稱(chēng)并且 pg_cast
提供了一種從
x
的類(lèi)型到這種 類(lèi)型的二進(jìn)制可強(qiáng)制造型,那么該調(diào)用將被翻譯為一次二進(jìn)制可強(qiáng)制造型。 通過(guò)這種例外,二進(jìn)制可強(qiáng)制造型能夠以函數(shù)語(yǔ)法調(diào)用,即便沒(méi)有該函數(shù)。 同樣的,如果沒(méi)有pg_cast
項(xiàng),但是該造型是要造型到一種 字符串類(lèi)型或者是要從一種字符串類(lèi)型造型,調(diào)用將被翻譯成一次 I/O 轉(zhuǎn)換 造型。這種例外允許以函數(shù)語(yǔ)法調(diào)用 I/O 轉(zhuǎn)換造型。
還有一種例外中的例外:從組合類(lèi)型到字符串類(lèi)型的 I/O 轉(zhuǎn)換造型不能使用 函數(shù)語(yǔ)法調(diào)用,而必須被寫(xiě)成顯式造型語(yǔ)法(CAST
或者 ::
記號(hào))。增加這種例外是因?yàn)樵谝肓俗詣?dòng)提供的 I/O 轉(zhuǎn)換 造型之后,在想要引用一個(gè)函數(shù)或者列時(shí)太容易意外地調(diào)用這種造型。
要使用函數(shù)int4(bigint)
創(chuàng)建一種從類(lèi)型 bigint
到類(lèi)型int4
的賦值造型:
CREATE CAST (bigint AS int4) WITH FUNCTION int4(bigint) AS ASSIGNMENT;
(在系統(tǒng)中這種造型已經(jīng)被預(yù)定義)。
CREATE CAST
命令符合 SQL標(biāo)準(zhǔn),不過(guò) SQL 沒(méi)有為二進(jìn)制可強(qiáng)制 類(lèi)型或者實(shí)現(xiàn)函數(shù)的額外參數(shù)做好準(zhǔn)備。 AS IMPLICIT
也是一種 PostgreSQL擴(kuò)展。
Copyright©2021 w3cschool編程獅|閩ICP備15016281號(hào)-3|閩公網(wǎng)安備35020302033924號(hào)
違法和不良信息舉報(bào)電話:173-0602-2364|舉報(bào)郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號(hào)
聯(lián)系方式:
更多建議: