?
Dieses Dokument verwendet PHP-Handbuch für chinesische Websites Freigeben
下面講解的過程解釋了如何在一次操作符調(diào)用中確定所使用的究竟是哪個(gè)操作符。 請注意這個(gè)過程受被調(diào)用操作符的優(yōu)先級影響。參閱Section 4.1.6獲取更多信息
操作符類型解析
從系統(tǒng)表pg_operator
中選出要考慮的操作符。如果使用了一個(gè)不帶修飾的操作符
名(常見的狀況),那么認(rèn)為該操作符是那些在當(dāng)前搜索路徑中名字和參數(shù)個(gè)數(shù)都正確的
操作符(參閱 Section 5.7.3)。
如果給出一個(gè)帶修飾的操作符名,那么只考慮指定模式中的操作符。
如果搜索路徑中找到了多個(gè)相同參數(shù)類型的操作符,那么只考慮最早出現(xiàn)在路徑中的那一個(gè)。 但是不同參數(shù)類型的操作符將被平等看待,而不管它們在路徑中的位置如何。
查找精確接受輸入?yún)?shù)類型的操作符。如果找到一個(gè)(在一組被考慮的操作符中,可能只存在一個(gè)精確匹配的), 則用之。
如果一個(gè)雙目操作符調(diào)用中的一個(gè)參數(shù)是unknown類型,則在本次檢查中假設(shè)其與另一個(gè)參數(shù)類型相同。 其它涉及unknown的情況絕不會在此處找到匹配。
尋找最優(yōu)匹配。
拋棄那些輸入類型不匹配并且也不能隱式轉(zhuǎn)換成匹配的候選操作符。unknown文本在這種情況下 可以轉(zhuǎn)換成任何東西。如果只剩下一個(gè)候選項(xiàng),則用之,否則繼續(xù)下一步。
遍歷所有候選操作符,保留那些輸入類型匹配最準(zhǔn)確的。此時(shí),域被看作和他們的基本類型相同。如果沒有一個(gè)操作符能被保留,則保留所有候選。 如果只剩下一個(gè)候選項(xiàng),則用之,否則繼續(xù)下一步。
遍歷所有候選操作符,保留那些需要類型轉(zhuǎn)換時(shí)接受(屬于輸入數(shù)據(jù)類型的類型范疇的)首選類型位置 最多的操作符。如果沒有接受首選類型的操作符,則保留所有候選。如果只剩下一個(gè)候選項(xiàng),則用之, 否則繼續(xù)下一步。
如果有任何輸入?yún)?shù)是 unknown類型,檢查剩余的候選操作符對應(yīng)參數(shù)位置的類型范疇。 在每一個(gè)能夠接受字符串類型范疇的位置使用string類型(這種對字符串的偏愛是合適的, 因?yàn)?tt class="TYPE">unknown文本確實(shí)像字符串)。另外,如果所有剩下的候選操作符都接受相同的類型 范疇,則選擇該類型范疇,否則拋出一個(gè)錯(cuò)誤(因?yàn)樵跊]有更多線索的條件下無法作出正確 的選擇)?,F(xiàn)在拋棄不接受選定的類型范疇的候選操作符,然后,如果任意候選操作符在 某個(gè)給定的參數(shù)位置接受一個(gè)首選類型, 則拋棄那些在該參數(shù)位置接受非首選類型的候選操作符。
如果只剩下一個(gè)操作符,則用之。如果還有多個(gè)候選操作符或者沒有候選操作符,則產(chǎn)生一個(gè)錯(cuò)誤。
下面是一些例子。
Example 10-1. 指數(shù)操作符類型解析
只有一個(gè)在標(biāo)準(zhǔn)目錄里被指定階乘的操作符,它接受一個(gè)參數(shù)類型bigint。 掃描器為在查詢表達(dá)式中的參數(shù)指定一個(gè)初始類型integer:
SELECT 40 ! AS "40 factorial"; 40 factorial -------------------------------------------------- 815915283247897734345611269596115894272000000000 (1 row)
因此,解析器在操作數(shù)上做了一個(gè)類型轉(zhuǎn)換,該查詢相當(dāng)于:
SELECT CAST(40 AS bigint) ! AS "40 factorial";
Example 10-2. 字符串連接操作符類型解析
一個(gè)類字符串性的語法用來處理字符串類型和處理復(fù)雜的擴(kuò)展類型。 為指定類型的字符串與候選操作符進(jìn)行匹配。
一個(gè)未指定參數(shù)的例子:
SELECT text 'abc' || 'def' AS "text and unknown"; text and unknown ------------------ abcdef (1 row)
在這種情況下,掃描器查看是否有一個(gè)對兩個(gè)參數(shù)使用了text的操作符。 既然有,那么它假設(shè)第二個(gè)參數(shù)應(yīng)被解釋為text類型。
下面是一個(gè)未指定類型的連接:
SELECT 'abc' || 'def' AS "unspecified"; unspecified ------------- abcdef (1 row)
在這種情況下,沒有對于所使用的類型的初始提示,因?yàn)闆]有在查詢中指定類型。 因此,解析器查找所有的候選操作符并找到同時(shí)接受字符串類別和比特串類別的輸入。 因?yàn)楫?dāng)可用時(shí)字符串類型是首選的,該類型被選中,并且對于字符串的首選類型, text作為解決未知文字的指定類型。
Example 10-3. 絕對值與否定操作符類型解析
PostgreSQL操作符目錄中有幾個(gè)對于前綴操作符@的條目, 這些都現(xiàn)實(shí)了針對各種數(shù)字?jǐn)?shù)據(jù)類型的絕對值操作符。 其中有一條為float8類型,它是在數(shù)字類型中首選的類型。 因此,PostgreSQL將在遇到一個(gè)未知類型的輸入時(shí)使用它:
SELECT @ '-4.5' AS "abs"; abs ----- 4.5 (1 row)
在這里,系統(tǒng)在接受選取操作符之前已經(jīng)隱含地解決了將未知類型文字作為float8類型。 我們可以確認(rèn)我們使用的是float8而不是別的類型:
SELECT @ '-4.5e500' AS "abs"; ERROR: "-4.5e500" 超出了雙精度類型范圍
另一方面,前綴符~只在整數(shù)數(shù)據(jù)類型的時(shí)候被指定,并不是為float8。 因此,如果我們嘗試一個(gè)使用~的類似操作,我們可以這樣:
SELECT ~ '20' AS "negation"; ERROR: 操作符不唯一: ~ "未知" HINT: 不能選擇一個(gè)最佳的候選操作符。你或許需要添加顯式類型。
此情況的發(fā)生是由于系統(tǒng)不能決定在幾個(gè)可能的~符號中哪個(gè)是指定的。 我們可以幫助它做出一個(gè)明確的選擇:
SELECT ~ CAST('20' AS int8) AS "negation"; negation ---------- -21 (1 row)