SQL 查詢可能(有意無意地)要求在同一表達式裡混合不同的資料類型. PostgreSQL 在計算混合類型表達式方面有許多擴展性很強的功能。
在大多數情況下,使用者不需要明白類型轉換機制的細節. 但是,由 PostgreSQL 所進行的隱含的類型轉換會對查詢的結果產生影響,必要時這些影響又可以由用 戶或程式員通過明確的類型轉換進行剪裁利用.
本章介紹 PostgreSQL類型轉換的傳統和機制。 關於特定的類型和函數及運算子的進一步資訊, 請參考Chapter 5 和 Chapter 6裡的相關章節。
在PostgreSQL 7.3 程式員手冊 裡有關於隱含類型轉換使用的具體算法的更詳細介紹.
SQL 是強類型語言。 也就是說,每一資料都與一個決定其行為和可行用法的資料類型相聯。 PostgreSQL 有一個可擴展的資料類型系統, 該系統比其他 SQL 實現 實現更具通用性和靈活性。 因而,PostgreSQL中 大多數類型轉換的特性應該是由通用規則來管理的, 而不是由專門搜尋方法來分析, 以此令混合類型表達式有實際意義, 即便是使用者定義的類型也如此。
PostgreSQL 掃描/分析器只將詞法元素分解成五個基本種類: 整數(integers),浮點數(floating-point numbers), 字串(strings),名字(names)和關鍵字 (keywords). 大多數擴展的類型首先表征為字串(strings). SQL 語言的定義允許將類型名宣告為字串,這個機制被 PostgreSQL用於令分析器沿著正確 的方向運行.例如,下面查詢
tgl=> SELECT text 'Origin' AS "Label", point '(0,0)' AS "Value"; Label | Value --------+------- Origin | (0,0) (1 row)
有兩個純文字常數,類型分別為 text 和 point. 如果沒有為字串純文字宣告類型, (該純文字)先被初始化成一個擁有儲存空間的 unknown(未知)類型, 該類型將在後面描述的晚期階段分析.
在 PostgreSQL 分析器裡, 有四種基本的 SQL 元素需要獨立的類型轉換規則:
PostgreSQL 也允許使用左目或右目運算子(單目運算子,一個參數), 允許表達式裡使用雙目運算子(兩個參數).
多數 PostgreSQL 類型系統是建筑在一套丰富的函數上的. 任何查詢中調用的函數的參數,不管是一個還是多個, 必須符合該函數在系統表裡的定義. 因為 PostgreSQL 允許函數重載, 所以函數名自身並不唯一地標識將要調用的函數 --- 分析器必須以 函數提供的參數的類型為基礎選擇正確的函數.
SQL INSERT和UPDATE 語句將表達式結果放入表中. 查詢表達式的類型必須和的目標列的類型一致或者是(可能需要)轉換成一致的.
因為聯合SELECT語句的所有查詢結果必須在一列裡顯示出來, 所以每個SELECT 幾句中的元素類型必須相互相符並轉換成一套統一類型. 類似,一個CASE構造的結果表達式必須轉換成統一的類型, 這樣CASE表達式自身作為整體有一種已知輸出類型.
許多通用的類型轉換規則使用建立在 PostgreSQL 函數和運算子系統表基礎上的簡單轉換來實現. 在轉換規則中包括了一些啟發方法,以便更好的支援 SQL 標準中的傳統的內建類型,像 smallint,integer,和 real.
! The system catalogs store information about which conversions, called ! casts, between data types are valid, and how to ! perform those conversions. Additional casts can be added by the user ! with the CREATE CAST command. (This is usually ! done in conjunction with defining new data types. The set of casts ! between the built-in types has been carefully crafted and should not ! be altered.) 系統表儲存有關哪種資料類型之間的轉換(叫 casts ) 是合法的,以及如何執行這些轉換的資訊。額外的轉換可以由使用者通過 CREATE CAST 命令增加。(通常和定義一種新的資料類型 一起完成。內建類型的類型轉換集已經經過仔細的雕琢了,因此不要去變更它們。)
分析器中還有一個搜尋器用於更好地猜測 SQL 標準類型的確切特性. 分析器裡定義了幾種類型範疇: boolean,numeric,string, bitstring,datetime,timespan, geometric,network,和使用者定義(user-defined). 除使用者定義類型外, 每種類型都有一種優選類型用於解決類型定義歧義的問題. 每一個"使用者定義"的類型就是其自身的"優選類型",所以那些含混不清的 表達式(在分析結果中有多種可能的表達式) 如果有多個內建類型的時候大多可以正確分析,但如果有多個使用者定義類型 可選,則會拋出錯.
所有類型轉換規則都是建立在下面幾個基本原則上的:
隱含轉換決不能有奇怪的或不可預見的輸出.
使用者定義類型,因為分析器對其沒有預先的認識, 在類型級別中應該級別較"高". 在混合類型的表達式裡,內部類型總是應該轉換成使用者定義類型. (當然只是在必須轉換的時候).
使用者定義類型是不相關的.目前,PostgreSQL 除了用於內部資料類型的硬代碼搜尋器和以系統表中現有函數為基礎的 隱含類型關系外,沒有任何可用於處理類型間關系的資訊。
如果一個查詢不需要隱含的類型轉換, 分析器或執行器不應該進行更多的額外操作. 這就是說,任何一個類型相符,格式清晰的查詢不應該在分析器裡耗費更多的時間, 也不應該向查詢中引入任何不必要的隱含類型轉換函數.
另外,如果一個查詢通常使用某個函數進行隱含類型轉換, 而使用者明確定義了一個有正確參數的函數,解釋器應該 使用新函數取代原先舊函數的隱含操作。