?
This document uses PHP Chinese website manual Release
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 定義一個(gè)新的轉(zhuǎn)換。一個(gè)轉(zhuǎn)換說(shuō)明如何在兩個(gè)類(lèi)型之間進(jìn)行轉(zhuǎn)換。比如:
SELECT CAST(42 AS float8);
通過(guò)調(diào)用前面指定的函數(shù)將整數(shù)常量42轉(zhuǎn)化為float8類(lèi)型,按照 float8(int4)的形式。(如果沒(méi)有定義合適的投射, 轉(zhuǎn)換將失敗。)
兩種形式是二進(jìn)制可壓縮的,這意味轉(zhuǎn)換可以在不調(diào)用函數(shù)的情況下 自由執(zhí)行。這要求相應(yīng)的值使用相同的內(nèi)部表示。例如,text和varchar 形式都是二進(jìn)制可強(qiáng)制的兩種方法。二進(jìn)制可壓縮性未必是一個(gè)對(duì)稱(chēng)的關(guān)系。例如: xml到text的映射可以在當(dāng)前的映射中自由執(zhí)行。但相反的方向需要一個(gè)函數(shù) 來(lái)執(zhí)行至少一個(gè)語(yǔ)法檢查。(兩種二進(jìn)制可強(qiáng)迫的形式也被稱(chēng)為二進(jìn)制兼容。)
您可以定義一個(gè)映射為使用 WITH INOUT語(yǔ)法的I/O轉(zhuǎn)化映射。 一個(gè)I/O轉(zhuǎn)化映射通過(guò)調(diào)用原數(shù)據(jù)庫(kù)類(lèi)型的輸出函數(shù)來(lái)執(zhí)行,并將結(jié)果傳給 目標(biāo)數(shù)據(jù)類(lèi)型的輸入函數(shù)。
缺省時(shí),只有在明確要求轉(zhuǎn)換的情況下才調(diào)用一個(gè)轉(zhuǎn)換,也就是一個(gè)明確的 CAST(x AS typename)或 x::typename構(gòu)造。
如果轉(zhuǎn)換被標(biāo)記為AS ASSIGNMENT,那么在給目標(biāo)數(shù)據(jù)類(lèi)型的字段賦值的時(shí)候, 可以隱含調(diào)用它。比如,假設(shè)foo.f1是一個(gè)類(lèi)型為text的字段, 那么:
INSERT INTO foo (f1) VALUES (42);
如果從integer類(lèi)型到text類(lèi)型的轉(zhuǎn)換標(biāo)記為AS ASSIGNMENT,上面的這句就被允許,否則就不允許。(通常用術(shù)語(yǔ)assignment cast來(lái)描述這種轉(zhuǎn)換。)
若果映射標(biāo)記了AS IMPLICIT,那么可以在任何環(huán)境下調(diào)用,不管是 作業(yè)還是在一個(gè)內(nèi)部表達(dá)式中。(我們通常使用術(shù)語(yǔ)implicit cast 來(lái)描述這種映射。 例如,考慮下面這個(gè)查詢(xún);)
SELECT 2 + 4.0;
解析器初始時(shí)標(biāo)記常量分別為integer和numeric。 在系統(tǒng)目錄中沒(méi)有integer + numeric, 但是有一個(gè)numeric + numeric操作符。 若integer到numeric的映射是可獲得的并且標(biāo)記為 AS IMPLICIT — 則該查詢(xún)將因此獲得成功。解析器將使用隱性的映射并按所寫(xiě)的處理查詢(xún)。
SELECT CAST ( 2 AS numeric ) + 4.0;
現(xiàn)在,目錄提供了一個(gè)從numeric到integer的映射。 如果那個(gè)映射標(biāo)記了 AS IMPLICIT —而它并不是— 然后解析器會(huì)面臨對(duì)選擇上面的解釋還是選擇numeric常量到integer的 映射以及應(yīng)用integer + integer 操作符。 缺乏選擇優(yōu)等項(xiàng)的能力,則會(huì)將放棄和聲明查詢(xún)模棱兩可的。兩映射中僅有一個(gè) 是陰性的事實(shí)正是我們?cè)O(shè)計(jì)的方式,我們讓解析器更偏向于將numeric-and-integer 的混合表達(dá)式的結(jié)果視作numeric;沒(méi)有關(guān)于那方面的內(nèi)置知識(shí)。
在是否將轉(zhuǎn)換標(biāo)記為隱含的問(wèn)題上保守一些是明智的。過(guò)于豐富的隱含轉(zhuǎn)換路徑 會(huì)導(dǎo)致PostgreSQL選擇讓人奇怪的命令解析,或者 是完全不能解析命令,因?yàn)榇嬖诙鄠€(gè)可能的解析。一條好的拇指定律是,只有在同 一個(gè)通用類(lèi)型范疇里面的那些可以保留轉(zhuǎn)換信息的類(lèi)型之間才標(biāo)記為可隱含調(diào)用轉(zhuǎn)換。 比如,從int2到int4可以合理地標(biāo)記為隱含轉(zhuǎn)換,但 是從float8到int4也許應(yīng)該標(biāo)記為賦值轉(zhuǎn)換??珙?lèi)型 范疇的轉(zhuǎn)換,比如text到int4,最好只能明確地轉(zhuǎn)換。
Note: 有時(shí),有必要為了可用性和標(biāo)準(zhǔn)支持的原因在一組類(lèi)型中提供多個(gè)隱式投射,導(dǎo)致上述 無(wú)法避免的模棱兩可的問(wèn)題。解析器有一個(gè)基于type categories和 preferred types的撤銷(xiāo)啟發(fā)式,有助于在這種情況下提供所期望的行為。 參閱CREATE TYPE獲取更多詳細(xì)信息。
為了能夠創(chuàng)建一個(gè)映射,您必須擁有源或者目標(biāo)數(shù)據(jù)類(lèi)型。為了創(chuàng)建一個(gè)強(qiáng)制 二進(jìn)制的映射,您必須是超級(jí)用戶(hù)。(做這個(gè)約束的原因是錯(cuò)誤的二進(jìn)制可強(qiáng)迫映射 轉(zhuǎn)換可以很容易摧毀服務(wù)器。)
轉(zhuǎn)換的源數(shù)據(jù)類(lèi)型
轉(zhuǎn)換的目標(biāo)數(shù)據(jù)類(lèi)型
用于執(zhí)行轉(zhuǎn)換的函數(shù)。這個(gè)函數(shù)名可以是用模式名修飾的。如果它沒(méi)有用模式名修飾, 那么該函數(shù)將從模式搜索路徑中找出來(lái)。函數(shù)的結(jié)果數(shù)據(jù)類(lèi)型必須匹配轉(zhuǎn)換的目標(biāo)類(lèi)型。 它的參數(shù)在下面討論。
表明源類(lèi)型是對(duì)目標(biāo)類(lèi)型強(qiáng)制二進(jìn)制的,所以沒(méi)有函數(shù)需要執(zhí)行此映射。
表明投影是I/O轉(zhuǎn)換投影,通過(guò)調(diào)用源數(shù)據(jù)類(lèi)型的輸出函數(shù)來(lái)執(zhí)行,并將結(jié)果傳給目標(biāo)數(shù)據(jù)類(lèi)型的 輸入函數(shù)。
表示轉(zhuǎn)換可以在賦值環(huán)境里隱含調(diào)用
表示轉(zhuǎn)換可以在任何環(huán)境里隱含調(diào)用
映射實(shí)現(xiàn)函數(shù)可以有一到三個(gè)參數(shù)。第一個(gè)參數(shù)的類(lèi)型必須與映射的源類(lèi)型相同的,或 可以從映射的源類(lèi)型二進(jìn)制壓縮的。第二個(gè)參數(shù),如果存在,必須是integer 類(lèi)型;它接收這些與目標(biāo)類(lèi)型相關(guān)聯(lián)的類(lèi)型修飾符,或者若什么都沒(méi)有則是-1。 第三個(gè)參數(shù),如果存在,必須是boolean類(lèi)型;若映射是一個(gè)顯式類(lèi)型轉(zhuǎn)換則會(huì) 收到true,否則是false。(奇怪的是,在一些情況系SQL標(biāo)準(zhǔn)要 求對(duì)顯式和隱式映射的不同表現(xiàn)。我們不推薦您設(shè)計(jì)自己的數(shù)據(jù)類(lèi)型,這很重要。)
一個(gè)映射函數(shù)的返回類(lèi)型必須是與映射的目標(biāo)類(lèi)型相同或者對(duì)映射的 目標(biāo)類(lèi)型二進(jìn)制可壓縮。
通常,一個(gè)映射必須有不同的源和目標(biāo)數(shù)據(jù)類(lèi)型。然而,若有帶多于一個(gè)參數(shù)的 映射實(shí)現(xiàn)函數(shù),則允許聲明一個(gè)有相同的源和目標(biāo)類(lèi)型的映射。 這用于表示系統(tǒng)目錄中的特定類(lèi)型的長(zhǎng)度強(qiáng)制函數(shù)。命名的函數(shù)用于 強(qiáng)制一個(gè)該類(lèi)型的值為第二個(gè)參數(shù)給出的類(lèi)型修飾符值。
如果一個(gè)類(lèi)型轉(zhuǎn)換的源類(lèi)型和目標(biāo)類(lèi)型不同,并且接收多于一個(gè)參數(shù),它就表示從一種 類(lèi)型轉(zhuǎn)換成另外一種類(lèi)型只用一個(gè)步驟,并且同時(shí)實(shí)施長(zhǎng)度轉(zhuǎn)換。如果沒(méi)有這樣的項(xiàng)可用, 那么轉(zhuǎn)換成一個(gè)使用了類(lèi)型修飾詞的類(lèi)型將涉及兩個(gè)步驟,一個(gè)是在數(shù)據(jù)類(lèi)型之間轉(zhuǎn)換, 另外一個(gè)是施加修飾詞。
使用DROP CAST刪除用戶(hù)定義的映射。
請(qǐng)注意,如果希望能雙向轉(zhuǎn)換類(lèi)型,那么你需要明確地定義兩個(gè)方向的轉(zhuǎn)換。
通常不需要?jiǎng)?chuàng)建用戶(hù)定義類(lèi)型與標(biāo)準(zhǔn)字符串類(lèi)型之間的映射(text, varchar, 和 char(n), 以及被定義為字符串的范疇的用戶(hù)定義的類(lèi)型)。 PostgreSQL為此提供自動(dòng)I/O轉(zhuǎn)換映射。字符串類(lèi)型的自動(dòng)映射可以認(rèn)為是 分配映射,而來(lái)自字符串的自動(dòng)映射是唯一顯式的。您可以通過(guò)聲明自己的映射替換自動(dòng)映射 來(lái)重寫(xiě)此性能,但是,通常這么做的唯一原因是,你想讓轉(zhuǎn)化比標(biāo)準(zhǔn)唯一分配或者唯一顯式 設(shè)置更容易調(diào)用。另一個(gè)可能的原因是你想讓轉(zhuǎn)化變現(xiàn)的不同于類(lèi)型的I/O函數(shù);但是足夠驚人的是 您應(yīng)該反復(fù)考慮這是否是一個(gè)好主意。(少量?jī)?nèi)部類(lèi)型確實(shí)對(duì)轉(zhuǎn)換有不同的性能要求,大部分是 因?yàn)橐骃QL標(biāo)準(zhǔn)。)
在PostgreSQL7.3之前,每個(gè)與數(shù)據(jù)類(lèi)型有相同名稱(chēng),會(huì)返回那個(gè) 數(shù)據(jù)類(lèi)型,并取一個(gè)不同類(lèi)型的參數(shù)的函數(shù),自動(dòng)成為一個(gè)映射函數(shù)。 在面臨模式引入時(shí)約定已取消并且能代表系統(tǒng)表中的二進(jìn)制可強(qiáng)制映射。內(nèi)置的映射 功能仍然遵循這種命名模式,但是他們必須像系統(tǒng)表pg_cast中的映射 一樣顯示。
雖然不是必須的,但是還是建議你遵循舊的命名類(lèi)型轉(zhuǎn)換實(shí)現(xiàn)函數(shù)的習(xí)慣,也就是說(shuō), 函數(shù)名和目標(biāo)數(shù)據(jù)類(lèi)型同名。許多用戶(hù)習(xí)慣于使用函數(shù)風(fēng)格的表示法 typename(x)來(lái)做數(shù)據(jù)類(lèi)型轉(zhuǎn)換。這種表示法恰好 就是調(diào)用類(lèi)型轉(zhuǎn)換實(shí)現(xiàn)函數(shù),這樣并不會(huì)被當(dāng)作一種類(lèi)型轉(zhuǎn)換而被特殊看待。如果你的 轉(zhuǎn)換函數(shù)沒(méi)有按照這種傳統(tǒng)命名,那么你就會(huì)讓用戶(hù)很奇怪。因?yàn)?span id="377j5v51b" class="PRODUCTNAME">PostgreSQL 允許同名不同參數(shù)的函數(shù)重載,因此同時(shí)存在多個(gè)從不同類(lèi)型向同樣類(lèi)型轉(zhuǎn)換的同名轉(zhuǎn) 換函數(shù)一點(diǎn)問(wèn)題都沒(méi)有。
Note: Actually the preceding paragraph is an oversimplification: there are two cases in which a function-call construct will be treated as a cast request without having matched it to an actual function. If a function call name(x) does not exactly match any existing function, but name is the name of a data type and pg_cast provides a binary-coercible cast to this type from the type of x, then the call will be construed as a binary-coercible cast. This exception is made so that binary-coercible casts can be invoked using functional syntax, even though they lack any function. Likewise, if there is no pg_cast entry but the cast would be to or from a string type, the call will be construed as an I/O conversion cast. This exception allows I/O conversion casts to be invoked using functional syntax. 事實(shí)上前節(jié)是過(guò)分簡(jiǎn)化的:在兩種情況下函數(shù)調(diào)用結(jié)構(gòu)被認(rèn)為是一個(gè)映射請(qǐng)求而不需 要將其匹配為一個(gè)實(shí)際函數(shù)。如果函數(shù)調(diào)用name(x) 不準(zhǔn)確匹配任何現(xiàn)有函數(shù),但是name是一個(gè)數(shù)據(jù)類(lèi)型的名稱(chēng)并且 pg_cast從x類(lèi)型提供了一個(gè)二進(jìn)制可強(qiáng)制映射到這個(gè)類(lèi)型。 設(shè)了該異常所以二進(jìn)制可強(qiáng)制映射可以通過(guò)使用功能性語(yǔ)法來(lái)調(diào)用,即使他們沒(méi)有任何函數(shù)。 同樣的,若無(wú)pg_cast條目,但映射會(huì)到達(dá)或者來(lái)自一個(gè)字符串類(lèi)型, 調(diào)用將會(huì)被視為一個(gè)I/O轉(zhuǎn)換映射。該異常允許I/O轉(zhuǎn)換映射通過(guò)使用功能性語(yǔ)法來(lái)調(diào)用。
為了從類(lèi)型bigint到類(lèi)型 int4創(chuàng)建一個(gè)指派映射要通過(guò)使用函數(shù)int4(bigint):
CREATE CAST (bigint AS int4) WITH FUNCTION int4(bigint) AS ASSIGNMENT;
(這個(gè)轉(zhuǎn)換在系統(tǒng)中已經(jīng)預(yù)先定義了。)
CREATE CAST指令符合SQL標(biāo)準(zhǔn), 除了SQL不會(huì)為二進(jìn)制可強(qiáng)制類(lèi)型或者實(shí)現(xiàn)函數(shù)的額外參數(shù)來(lái)指定條款。 AS IMPLICIT也是一個(gè)PostgreSQL擴(kuò)展。
CREATE FUNCTION, CREATE TYPE, DROP CAST