| PostgreSQL 8.0.0 中文文件(轉譯自 PostgreSQL 中國 製作的簡體中文版本) | ||||
|---|---|---|---|---|
| Prev | Fast Backward | Fast Forward | Next | |
CREATE CAST (sourcetype AS targettype)
WITH FUNCTION funcname (argtypes)
[ AS ASSIGNMENT | AS IMPLICIT ]
CREATE CAST (sourcetype AS targettype)
WITHOUT FUNCTION
[ AS ASSIGNMENT | AS IMPLICIT ]CREATE CAST 定義一個新的轉換。 一個轉換說明如何在兩個類型之間進行轉換。比如:
SELECT CAST(42 AS text);
透過調用前面聲明的一個函數,把整數常量 42 轉換成類型 text, 在這個例子裡是 text(int4)。(如果沒有預先定義好合適的轉換,那麼這個轉換失敗。)
兩種類型可以是二進制兼容的, 意思是它們之間可以"自由轉換"而不用調用任何函數。 這就需要那個對應的數值使用同樣的內部資料表現形式。 比如,類型 text 和 varchar 是二進制兼容的。
預設時,只有在明確要求轉換的情況下才調用一個轉換, 也就是一個明確的 CAST(x AS typename) 或者 x::typename 構造。
如果轉換標記為 AS ASSIGNMENT,那麼在賦一個數值給目標資料類型的字串的時候, 可以隱含調用它。比如,假設 foo.f1 是一個類型為 text 的字串,那麼
INSERT INTO foo(f1) VALUES (42);
如果從類型 integer 到類型 text 的轉換標記為 AS ASSIGNMENT, 上面的這句就被允許,否則就不允許。(我們通常用術語賦值轉換來描述這種轉換。)
如果轉換標記為 AS IMPLICIT,那麼它就可以在任何環境裡調用, 不管是賦值還是在資料表達式的內部。比如,因為 || 接受 text 操作數,
SELECT 'The time is ' || now();
將只有在類型 timestamp 到 text 的轉換標記為 AS IMPLICIT 的時候才允許。否則我們就必須明確書寫轉換, 比如
SELECT 'The time is ' || CAST(now() AS text);
(我們通常使用術語隱含轉換來描述這種類型的轉換。)
在標記轉換為隱含的這個問題上保守一些是明智的。 過於豐富的隱含轉換路徑會導致 PostgreSQL 選擇讓人奇怪的命令的解析, 或者是完全不能解析命令,因為存在多個可能的解析。 一條好的拇指定律是,只有在同一個通用類型資料表裡面的那些可以保留轉換訊息的類型之間才標記為可隱含調用轉換。 比如,從 int2 到 int4 可以合理地標記為隱含轉換,但是從 float8 到 int4 可能應該是標記為賦值轉換。跨類型資料表的轉換,比如 text 到 int4,最好是只能明確地轉換。
要想建立一個轉換,您必須擁有源或者目的資料類型。要建立一個二進制兼容的轉換, 您必須是超級用戶。(做這個限制是因為一種有問題的二進制兼容轉換可以很容易摧毀伺服器。)
轉換的源資料類型。
轉換的目標資料類型。
用於執行轉換的函數。這個函數名可以是用模式名修飾的。 如果它沒有用模式名修飾,那麼該函數將從模式搜索路徑中找出來。 函數的結果資料類型必須匹配轉換的目標類型。它的參數在下面討論。
資料表示源資料類型和目標資料類型是二進制兼容的, 所以不需要什麼函數來執行轉換。
資料表示轉換可以在賦值環境裡隱含調用。
資料表示這個轉換可以在任何環境裡隱含調用。
轉換實現函數可以有一到三個參數。第一個參數類型必須和轉換的源類型相同。 如果有第二個參數,那麼必須是類型 integer;它接收與目標類型相關聯的類型修飾詞, 如果沒有,就是 -1。如果有第三個參數,就必須是類型 boolean; 如果這個轉換是一個明確的轉換,那麼它收到 true,否則收到 false。 (不過,很奇怪的是,SQL 規範在某些場合下要求不同的明確和隱含轉換的行為。這個參數提供給那些必須實現這樣的轉換的函數。 我們不建議您設計需要如此處理自己的資料類型。)
正常情況下,類型轉換必須有不同的源類型和目標資料類型。不過我們允許聲明一個源類型和目標類型相同的類型轉換, 只要它有超過一個參數的類型轉換實現函數。這個函數用於在系統資料表裡資料表示類型相關的長度轉換函數。 此命名的函數用於轉換一個該類型的數值為其第二個參數給出的帶類型修飾詞的值。 (因為目前語法只允許某些內置的資料類型擁有類型修飾詞,因此這個特性對用戶定義的目標類型沒有什麼用,我們提到它只是為了完整。)
如果一個類型轉換的源類型和目的類型不同,並且接收多於一個參數, 它就資料表示用一個步驟從一種類型轉換成另外一種類型,並且同時施加長度轉換。 如果沒有這樣的條目可用,那麼轉換成一個使用了類型修飾詞的類型涉及兩個步驟, 一個是在資料類型之間轉換,另外一個是施加修飾詞。
用 DROP CAST 刪除用戶定義的轉換。
請注意,如果您想能雙向轉換類型,那麼您需要明確地定義兩個方向的轉換。
在 PostgreSQL 7.3 之前,如果一個函數的名字和一個資料類型相同, 並且返回該種資料類型,而且還接受另外一種類型的參數自動就是一個轉換函數。 這個傳統隨著模式的引入以及為了能在系統資料表種資料表示二進制兼容的轉換就被廢棄了。 內置的轉換函數仍然遵循這個命名規則,但是它們現在同時也在系統資料表 pg_cast 裡顯示為轉換。
雖然不是必須的,但是我們還是建議您遵循舊的命名類型轉換實現函數的習慣, 也就是說,函數名和目標資料類型同名。許多用戶習慣於使用函數風格的資料表示法來做資料類型轉換, 像這樣:typename(x)。 這種資料表示法恰好就是調用類型轉換實現函數;這樣並不會被當作一種類型轉換而特殊看待。 如果您的轉換函數沒有按照這種傳統命名,那麼您就會讓用戶很奇怪。 因為 PostgreSQL 允許同名不同參數的函數重載,因此同時存在多個從不同類型向同樣類型轉換的同名轉換函數一點問題都沒有。
注意: 前面的段落撒了一個小小的謊:仍然有一種情況下,系統將要使用 pg_cast 來解析一個明顯的函數調用的含義。 如果一個函數調用 name(x) 不匹配任何實際函數, 但 name 是一個資料類型的名字並且 pg_cast 顯示了它是從類型 x 到這種類型的一個二進制兼容的轉換, 那麼該調用將被構造成一個明確的轉換。存在這個例外就可以讓二進制兼容的類型轉換使用函數狀的語法調用, 即使他們缺少函數也可以。