?
本文檔使用 php中文網(wǎng)手冊(cè) 發(fā)布
[ WITH [ RECURSIVE ] with_query [, ...] ] SELECT [ ALL | DISTINCT [ ON ( expression [, ...] ) ] ] * | expression [ [ AS ] output_name ] [, ...] [ FROM from_item [, ...] ] [ WHERE condition ] [ GROUP BY expression [, ...] ] [ HAVING condition [, ...] ] [ WINDOW window_name AS ( window_definition ) [, ...] ] [ { UNION | INTERSECT | EXCEPT } [ ALL ] select ] [ ORDER BY expression [ ASC | DESC | USING operator ] [ NULLS { FIRST | LAST } ] [, ...] ] [ LIMIT { count | ALL } ] [ OFFSET start [ ROW | ROWS ] ] [ FETCH { FIRST | NEXT } [ count ] { ROW | ROWS } ONLY ] [ FOR { UPDATE | SHARE } [ OF table_name [, ...] ] [ NOWAIT ] [...] ] where from_item can be one of: [ ONLY ] table_name [ * ] [ [ AS ] alias [ ( column_alias [, ...] ) ] ] ( select ) [ AS ] alias [ ( column_alias [, ...] ) ] with_query_name [ [ AS ] alias [ ( column_alias [, ...] ) ] ] function_name ( [ argument [, ...] ] ) [ AS ] alias [ ( column_alias [, ...] | column_definition [, ...] ) ] function_name ( [ argument [, ...] ] ) AS ( column_definition [, ...] ) from_item [ NATURAL ] join_type from_item [ ON join_condition | USING ( join_column [, ...] ) ] and with_query is: with_query_name [ ( column_name [, ...] ) ] AS ( select ) TABLE { [ ONLY ] table_name [ * ] | with_query_name }
SELECT將從零個(gè)或更多表中返回記錄行。SELECT通常的處理如下:
(See WITH Clause below.) 在WITH列表中的所有查詢都被計(jì)算。這些可以有效地充當(dāng)在 FROM列表中可以被參照的臨時(shí)表。在FROM 中的一個(gè)引用多于一次的WITH查詢僅計(jì)算一次。
計(jì)算列出在FROM中的所有元素(FROM列表中 的每個(gè)元素都是一個(gè)實(shí)際的或虛擬的表)。 如果在FROM列表里聲明了多個(gè)元素,那么他們就交叉連接在一起 (參見下面的FROM子句子句)。
如果聲明了WHERE子句,那么在輸出中消除所有不滿足條件的行。 參見下面的 WHERE子句子句。
如果聲明了GROUP BY子句,輸出就分成匹配一個(gè)或多個(gè)數(shù)值的不同組里。 如果出現(xiàn)了HAVING子句,那么它消除那些不滿足給出條件的組。 參見下面的GROUP BY子句子句和 HAVING子句子句。
實(shí)際輸出行將使用SELECT輸出表達(dá)式針對(duì)每一個(gè)選中的行進(jìn)行計(jì)算。 參見下面的SELECT列表列表。
使用UNION, INTERSECT和EXCEPT可以把多個(gè)SELECT語句的輸出合并成一個(gè)結(jié)果集。 UNION操作符返回兩個(gè)結(jié)果集的并集。INTERSECT操作符返回兩個(gè)結(jié)果集的交集。 EXCEPT操作符返回在第一個(gè)結(jié)果集對(duì)第二個(gè)結(jié)果集的差集。不管哪種情況,重復(fù)的行都被刪除, 除非聲明了ALL。參閱下面的UNION 子句子句、INTERSECT子句子句、EXCEPT子句子句。
如果聲明了ORDER BY子句,那么返回的行將按照指定的順序排序。 如果沒有給出ORDER BY,那么數(shù)據(jù)行是按照系統(tǒng)認(rèn)為可以最快生成的順序給出的。 參閱下面的ORDER BY子句子句。
DISTINCT從結(jié)果中刪除那些重復(fù)的行。DISTINCT ON刪除那些匹配所有指定表達(dá)式的行。 ALL(缺省)將返回所有候選行,包括重復(fù)的。參閱下面的DISTINCT子句子句。
如果給出了LIMIT或FETCH FIRST)或 OFFSET子句,那么SELECT語句只返回結(jié)果行的一個(gè)子集。 參閱下面的LIMIT子句子句。
如果聲明了FOR UPDATE或FOR SHARE子句, 那么SELECT語句對(duì)并發(fā)的更新鎖住選定的行。參閱下面的FOR UPDATE/FOR SHARE子句子句。
您必須有SELECT權(quán)限用于SELECT命令中每一列。 使用FOR UPDATE或FOR SHARE還要求UPDATE權(quán)限。 (至少在如此選定的每表的一個(gè)列上。)
WITH子句允許您指定一個(gè)或者多個(gè)可以通過主查詢中的名稱參照的子句。 子查詢?cè)谡麄€(gè)主查詢期間有效地充當(dāng)臨時(shí)表或者視圖。
一個(gè)名稱(有模式修飾)必須對(duì)每個(gè)WITH查詢指定。根據(jù)需要, 可以指定一個(gè)列名列表;若省略了這些,列名可從主查詢省略。
如果RECURSIVE已指定,它允許一個(gè)子查詢通過名稱引用自身。 這樣一個(gè)子查詢必須按如下格式
non_recursive_term UNION [ ALL ] recursive_term
此時(shí)遞歸的自我參照必須出現(xiàn)在UNION的左邊一側(cè)。每個(gè)查詢中僅允許 一個(gè)遞歸的自我查詢。
RECURSIVE的另一個(gè)作用是WITH不需要配需: 一個(gè)查詢可以參照在列表后的另一個(gè)。(然而,循環(huán)引用,或者互遞歸,在這里沒有實(shí)現(xiàn)。) 沒有RECURSIVE,WITH查詢只能參照早些時(shí)候 在WITH中的同類的WITH查詢,
WITH查詢的一個(gè)有效性能是:每次執(zhí)行主查詢時(shí)他們僅評(píng)估一次, 即使主查詢引用過他們不止一次。
請(qǐng)參閱Section 7.8獲取其他信息。
FROM子句為SELECT聲明一個(gè)或者多個(gè)源表。 如果聲明了多個(gè)源表,那么結(jié)果就是所有源表的笛卡兒積(交叉連接)。 但是通常會(huì)添加一些條件,把返回行限制成笛卡兒積的一個(gè)小的子集。
The FROM子句可以包括下列元素:
一個(gè)現(xiàn)存的表或視圖的名字(可以有模式修飾)。如果聲明了ONLY,則只掃描該表; 否則,該表和所有其派生表(如果沒有聲明ONLY)都被掃描。
為那些包含別名的FROM項(xiàng)目取的別名。別名用于縮寫或者在自連接中消除歧義 (自連接中同一個(gè)表將掃描多次)。如果提供了別名,那么它就會(huì)完全隱藏表或者函數(shù)的實(shí)際名字; 比如,如果給出FROM foo AS f,那么SELECT剩下的東西必須把這個(gè)FROM項(xiàng)按照 f而不是foo引用。 如果寫了別名,也可以提供一個(gè)字段別名列表,這樣可以替換表中一個(gè)或者多個(gè)字段的名字。
可以在FROM子句里出現(xiàn)一個(gè)子SELECT。 它的輸出作用好像是為這條SELECT命令在其生存期里創(chuàng)建一個(gè)臨時(shí)表。 請(qǐng)注意這個(gè)子SELECT必須用園括弧包圍。并且必須給它一個(gè)別名。 當(dāng)然,VALUES同樣也可以在這里使用。
名可以提供與對(duì)一個(gè)表相同的方式。 一個(gè)WITH查詢通過寫其名稱來引用,正如查詢的名字是一個(gè)表名。 實(shí)際上WITH查詢?yōu)橹鞑樵冸[藏相同名稱的任何實(shí)際表。必要時(shí), 您可以通過模式修飾的表的名稱引用一個(gè)相同名稱的真實(shí)表。
函數(shù)(特別是那些返回結(jié)果集的函數(shù))調(diào)用可以出現(xiàn)在FROM子句里。 這么做就好像在這個(gè)SELECT命令的生命期中,把函數(shù)的輸出創(chuàng)建為一個(gè)臨時(shí)表一樣。 當(dāng)然也可以使用別名。如果寫了別名,還可以寫一個(gè)字段別名列表, 為函數(shù)返回的復(fù)合類型的一個(gè)或多個(gè)屬性提供名字替換。如果函數(shù)定義為返回record類型, 那么必須出現(xiàn)一個(gè)AS關(guān)鍵字或者別名, 后面跟著一個(gè)形如( column_name data_type [, ... ] )的字段定義列表。 這個(gè)字段定義列表必須匹配函數(shù)返回的字段的實(shí)際數(shù)目和類型。
下列之一
[ INNER ] JOIN
LEFT [ OUTER ] JOIN
RIGHT [ OUTER ] JOIN
FULL [ OUTER ] JOIN
CROSS JOIN
必須為INNER和OUTER連接類型聲明一個(gè)連接條件, 也就是NATURAL,ON join_condition或 USING (join_column [, ...])之一。 它們的含義見下文,對(duì)于CROSS JOIN而言,這些子句都不能出現(xiàn)。
一個(gè)JOIN子句組合兩個(gè)FROM項(xiàng)。 必要時(shí)使用圓括弧以決定嵌套的順序。 如果沒有圓括弧,JOIN從左向右嵌套。在任何情況下, JOIN都比逗號(hào)分隔的FROM項(xiàng)綁定得更緊。
CROSS JOIN和INNER JOIN生成一個(gè)簡(jiǎn)單的笛卡兒積, 和您在FROM的頂層列出兩個(gè)項(xiàng)的結(jié)果相同。 CROSS JOIN等效于INNER JOIN ON (TRUE),也就是說,沒有被條件刪除的行。 這種連接類型只是符號(hào)上的方便,因?yàn)樗鼈兒湍煤?jiǎn)單的FROM和WHERE的效果一樣。
LEFT OUTER JOIN返回笛卡兒積中所有符合連接條件的行, 再加上左表中通過連接條件沒有匹配右表行的那些行。這樣,左邊的行將擴(kuò)展成生成表的全長, 方法是在那些右表對(duì)應(yīng)的字段位置填上NULL 。請(qǐng)注意,只在計(jì)算匹配的時(shí)候, 才使用JOIN子句的條件,外層的條件是在計(jì)算完畢之后施加的。
相應(yīng)的,RIGHT OUTER JOIN返回所有內(nèi)連接的結(jié)果行, 加上每個(gè)不匹配的右邊行(左邊用NULL擴(kuò)展)。這只是一個(gè)符號(hào)上的便利, 因?yàn)榭偸强梢园阉D(zhuǎn)換成一個(gè)LEFT OUTER JOIN,只要把左邊和右邊的輸入對(duì)掉一下即可。
FULL OUTER JOIN返回所有內(nèi)連接的結(jié)果行, 加上每個(gè)不匹配的左邊行(右邊用NULL擴(kuò)展), 再加上每個(gè)不匹配的右邊行(左邊用NULL擴(kuò)展)。
join_condition是一個(gè)導(dǎo)致boolean 類型值的表達(dá)式(類似于一個(gè)WHERE子句)這指定在連接中哪些行認(rèn)為是匹配的。
一個(gè)生成boolean類型結(jié)果的表達(dá)式(類似WHERE子句),限定連接中那些行是匹配的。
一個(gè)形如USING ( a, b, ... )的子句, 是ON left_table.a = right_table.a AND left_table.b = right_table.b ...的縮寫。 同樣,USING蘊(yùn)涵著每對(duì)等效字段中只有一個(gè)包含在連接輸出中,而不是兩個(gè)都輸出的意思。
NATURAL是一個(gè)USING列表的縮寫, 這個(gè)列表說的是兩個(gè)表中同名的字段。
可選的WHERE條件有如下常見的形式:
WHERE condition
這里condition可以是任意生成類型為boolean的表達(dá)式。 任何不滿足這個(gè)條件的行都會(huì)從輸出中刪除。如果一個(gè)行的數(shù)值代入到條件中計(jì)算出來的結(jié)果為真, 那么該行就算滿足條件。
可選的GROUP BY子句的一般形式
GROUP BY expression [, ...]
GROUP BY將把所有在組合表達(dá)式上擁有相同值的行壓縮成一行。expression可以是一個(gè)輸入字段名字, 或者是一個(gè)輸出字段(SELECT列表項(xiàng))的名字或序號(hào),或者也可以是任意輸入字 段組成的表達(dá)式。在有歧義的情況下,一個(gè)GROUP BY的名字將被解釋成輸入字 段的名字,而不是輸出字段的名字。
如果使用了聚集函數(shù),那么就會(huì)對(duì)每組中的所有行進(jìn)行計(jì)算并生成一個(gè)單獨(dú)的值 (而如果沒有GROUP BY,那么聚集將對(duì)選出來的所有行計(jì)算 出一個(gè)單獨(dú)的值)。如果出現(xiàn)了GROUP BY,那么 SELECT列表表達(dá)式中再引用那些沒有分組的字段就是非法的, 除非放在聚集函數(shù)里,因?yàn)閷?duì)于未分組的字段,可能會(huì)返回多個(gè)數(shù)值。
可選的HAVING子句有如下形式:
HAVING condition
這里condition與為WHERE 子句里聲明的相同。
HAVING去除了一些不滿足條件的組行。它與WHERE不同: WHERE在使用GROUP BY之前過濾出單獨(dú)的行, 而HAVING過濾由GROUP BY創(chuàng)建的行。在 condition里引用的每個(gè)字段都必須無歧義地引用 一個(gè)分組的行,除非引用出現(xiàn)在一個(gè)聚集函數(shù)里。
HAVING的出現(xiàn)把查詢變成一個(gè)分組的查詢,即使沒有GROUP BY子句也這樣。 這一點(diǎn)和那些包含聚集函數(shù)但沒有GROUP BY子句的查詢里發(fā)生的事情是一樣的。 所有選取的行都被認(rèn)為會(huì)形成一個(gè)單一的組,而SELECT列表和HAVING子句只能從聚集函數(shù)里面引用表的字段。 這樣的查詢?cè)?tt class="LITERAL">HAVING條件為真的時(shí)候?qū)l(fā)出一個(gè)行,如果為非真,則返回零行。
可選的WINDOW子句有一般形式
WINDOW window_name AS ( window_definition ) [, ...]
此時(shí)window_name是一個(gè) 可以從隨后的窗口定義或者OVER子句引用的名稱,并且 window_definition是
[ existing_window_name ] [ PARTITION BY expression [, ...] ] [ ORDER BY expression [ ASC | DESC | USING operator ] [ NULLS { FIRST | LAST } ] [, ...] ] [ frame_clause ]
如果指定一個(gè)existing_window_name, 那么必須引用WINDOW列表中的一個(gè)更早的條目;如存在,新窗口從這個(gè)條目復(fù)制其分區(qū)子句, 及其排序子句。在這種情況下,新的窗口不能聲明其自身PARTITION BY子句, 并且它可以僅在復(fù)制窗口沒有一個(gè)ORDER BY子句時(shí)指定該子句,新窗口總是使用其自身的框 架條款;復(fù)制窗口不能指定一個(gè)框架條款。
PARTITION BY列表的元素以與GROUP BY子句 元素相同的形式來解譯,除了他們總是簡(jiǎn)單的表達(dá)式并且從不是一個(gè)輸出列的名稱或者編號(hào)。 另一個(gè)不同是這些表達(dá)式包含聚集函數(shù)調(diào)用,這些在常規(guī)GROUP BY子句中都是不允許的。 他們?cè)诖颂幵试S是因?yàn)殚_窗在分組和聚集之后發(fā)生。
同樣地,ORDER BY列表的元素以與ORDER BY子句 的元素相同的形式來解譯,除了這個(gè)表達(dá)式總是作為簡(jiǎn)單的表達(dá)式并且從不是一個(gè)輸出列的名稱或者編號(hào)。
可選的frame_clause為基于框架(并非全都基于此)的窗口函數(shù)定義 window frame。窗口框架是面向查詢的每一行的一組相關(guān)行(稱作current row)。 frame_clause可以作為下面中的一個(gè)
[ RANGE | ROWS ] frame_start [ RANGE | ROWS ] BETWEEN frame_start AND frame_end
此時(shí)frame_start和frame_end是以下其一
UNBOUNDED PRECEDING value PRECEDING CURRENT ROW value FOLLOWING UNBOUNDED FOLLOWING
若frame_end被省略,其默認(rèn)值為CURRENT ROW。 限制條件是frame_start不能是UNBOUNDED FOLLOWING, frame_end不能是UNBOUNDED PRECEDING, 并且frame_end選擇不能比frame_start選擇更早出現(xiàn)在 以上列表中—例如:不允許RANGE BETWEEN CURRENT ROW AND value PRECEDING。
默認(rèn)框架選項(xiàng)是RANGE UNBOUNDED PRECEDING,這與 RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW相同; 它將框架設(shè)置為分區(qū)中的所有行,在ORDER BY序列中是從當(dāng)前行的最后一個(gè)元素開始 (這意味著若無從則是所有行)。通常,UNBOUNDED PRECEDING表示框架從分區(qū)的第一 行開始,類似地UNBOUNDED FOLLOWING表示框架已分區(qū)的最后一行結(jié)束(不管是 RANGE或者ROWS模式)。在ROWS模式,CURRENT ROW 意味著框架以當(dāng)前行在ORDER BY序列中的首個(gè)獲最后一個(gè)元素開始或者結(jié)束。 value PRECEDING和valueFOLLOWING 目前僅允許在ROWS模式。他們表明框架以當(dāng)前行之前或者之后許多航開始或者結(jié)束。 value必須是一個(gè)不包含任何變量、聚集函數(shù)或者窗口函數(shù)的整型表達(dá)式。 該值不能為空或者負(fù)值;但可以為0,并且這時(shí)選擇當(dāng)前行本身。
注意ROWS選項(xiàng)可以產(chǎn)生不可預(yù)測(cè)的結(jié)果,如果ORDER BY序列 若ORDER BY序列不能唯一地排列行。RANGE選項(xiàng)是為了確保是 ORDER BY序列中的peers的行能得到同等對(duì)待;任何兩個(gè)對(duì)等行將會(huì)都在或 者都不在框架中。
一個(gè)WINDOW語句的目的是指定出現(xiàn)在 SELECT列表或者 ORDER BY子句中的 window functions的性能。這些函數(shù)可以通過在其OVER子句中的名稱 參照WINDOW子句條目。一個(gè)WINDOW子句條目任何地方都 不需要參照;若它不在查詢中使用,它將被忽略??梢允褂么翱诔绦蚨静恍枰魏?tt class="LITERAL">WINDOW, 盡管一個(gè)窗口函數(shù)調(diào)用可以直接在其OVER子句中指定其窗口定義。然而, WINDOW子句會(huì)在多于一個(gè)窗口函數(shù)需要相同窗口定義時(shí)保存輸入。
窗口函數(shù)在Section 3.5, Section 4.2.8和 Section 7.2.4中有詳細(xì)描述。
SELECT列表(在SELECT和FROM關(guān)鍵字之間的部分)聲明組成 SELECT語句的輸出行的表達(dá)式。這些表達(dá)式可以(并且通常也會(huì))引用在 FROM子句里面計(jì)算出來的字段。
就像在一個(gè)表中,一個(gè)SELECT的每個(gè)輸出列都有一個(gè)名稱。 在一個(gè)簡(jiǎn)單的SELECT中,該名稱僅用于標(biāo)記顯示的列,但當(dāng) SELECT是一個(gè)較大查詢的子查詢時(shí),名稱被較大查詢視為子查詢產(chǎn)生的 虛表的列名。為了指定用于輸出列的名稱,要在列表達(dá)式后寫 AS output_name。 (您可以省略AS,但只有當(dāng)所需的輸出名稱不匹配任何 PostgreSQL 關(guān)鍵字時(shí)(請(qǐng)參閱Appendix C)。)為了防止將來可能的關(guān)鍵字添加, 建議您要么寫AS要么用雙引號(hào)引起輸出名稱。) 如果你不指定一個(gè)列名稱,PostgreSQL會(huì)自動(dòng)選擇 一個(gè)名稱。如果列的表達(dá)式是一個(gè)簡(jiǎn)單的列參照,那么選擇的名稱與列名相同; 在更復(fù)雜的情況下,同?columnN?的生成名 通常會(huì)被選擇。
一個(gè)輸出列的名稱可以用來參考ORDER BY和GROUP BY子句中的 列的值,而不是在WHERE或者HAVING子句中的;反而您必須在 那里寫出表達(dá)式。
除了表達(dá)式,也可以在輸出列表中使用*表示所有字段。 還可以用table_name.* 作為來自該表的所有字段的縮寫。 在這西情況下用AS指定新名稱是不可能的;輸出列的名稱將會(huì)與表列的名稱 相同。
UNION子句的一般形式是:
select_statement UNION [ ALL ] select_statement
這里的select_statement是任意沒有 ORDER BY,LIMIT,FOR UPDATE或 FOR SHARE子句的SELECT語句。 如果用圓括弧包圍,ORDER BY和LIMIT可以附著在子表達(dá)式里。 如果沒有圓括弧,這些子句將交給UNION的結(jié)果使用,而不是給它們右邊的輸入表達(dá)式。
UNION操作符計(jì)算那些涉及到的所有SELECT語句返回的行的結(jié)果聯(lián)合。 一個(gè)行如果至少在兩個(gè)結(jié)果集中的一個(gè)里面出現(xiàn),那么它就會(huì)在這兩個(gè)結(jié)果集的集合聯(lián)合中。 兩個(gè)作為UNION直接操作數(shù)的SELECT必須生成相同數(shù)目的字段, 并且對(duì)應(yīng)的字段必須有兼容的數(shù)據(jù)類型。
缺省的UNION結(jié)果不包含任何重復(fù)的行,除非聲明了ALL子句。ALL 制止了消除重復(fù)的動(dòng)作。 因此,UNION ALL通常比UNION明顯要快,可能的情況下盡量使用ALL。
同一個(gè)SELECT語句中的多個(gè)UNION操作符是從左向右計(jì)算的, 除非用圓括弧進(jìn)行了標(biāo)識(shí)。
目前,FOR UPDATE和FOR SHARE不能在UNION的結(jié)果或輸入中聲明。
INTERSECT子句的一般形式是:
select_statement INTERSECT [ ALL ] select_statement
select_statement是任何不帶ORDER BY,LIMIT,FOR UPDATE或 FOR SHARE子句的SELECT語句。
INTERSECT計(jì)算涉及的SELECT語句返回的行集合的交集。 如果一個(gè)行在兩個(gè)結(jié)果集中都出現(xiàn),那么它就在兩個(gè)結(jié)果集的交集中。
INTERSECT 的結(jié)果不包含任何重復(fù)行,除非您聲明了ALL選項(xiàng)。用了ALL以后, 一個(gè)在左邊的表里有m個(gè)重復(fù)而在右邊表里有n個(gè)重復(fù)的 行將出現(xiàn)min(m,n)次。
除非用圓括號(hào)指明順序,同一個(gè)SELECT語句中的多個(gè) INTERSECT操作符是從左向右計(jì)算的。 INTERSECT比UNION綁定得更緊, 也就是說A UNION B INTERSECT C將理解成A UNION (B INTERSECT C),除非您用圓括弧聲明。
目前,不能給INTERSECT的結(jié)果或者任何INTERSECT 的輸入聲明FOR UPDATE和FOR SHARE。
EXCEPT子句有如下的通用形式:
select_statement EXCEPT [ ALL ] select_statement
select_statement是任何沒有ORDER BY,LIMIT,FOR UPDATE或者 FOR SHARE子句的SELECT表達(dá)式。
EXCEPT操作符計(jì)算存在于左邊SELECT語句的輸出而不存在于 右邊SELECT語句輸出的行。
EXCEPT的結(jié)果不包含任何重復(fù)的行, 除非聲明了ALL選項(xiàng)。使用ALL時(shí), 一個(gè)在左邊表中有m個(gè)重復(fù)而在右邊表中有n個(gè)重復(fù)的行將在結(jié)果中出現(xiàn) max(m-n,0)次。
除非用圓括弧指明順序,否則同一個(gè)SELECT語句中的多個(gè)EXCEPT操作符是從左向右計(jì)算的。 EXCEPT和UNION的綁定級(jí)別相同。
目前,不能給EXCEPT的結(jié)果或者任何EXCEPT的輸入聲明FOR UPDATE或FOR SHARE子句。
可選的ORDER BY子句有下面的一般形式:
ORDER BY expression [ ASC | DESC | USING operator ] [ NULLS { FIRST | LAST } ] [, ...]
ORDER BY子句導(dǎo)致結(jié)果行根據(jù)指定的表達(dá)式進(jìn)行排序。 如果根據(jù)最左邊的表達(dá)式,兩行的結(jié)果相同,那么就根據(jù)下一個(gè)表達(dá)式進(jìn)行比較, 依此類推。如果對(duì)于所有聲明的表達(dá)式他們都相同,那么按隨機(jī)順序返回。
expression可以是一個(gè)輸出字段(SELECT列表項(xiàng))的名字或者序號(hào), 或者也可以是用輸入字段的數(shù)值組成的任意表達(dá)式。
序數(shù)指的是輸出字段按順序(從左到右)的位置。這個(gè)特性可以對(duì)沒有唯一名稱的字段進(jìn)行排序。 這不是必須的,因?yàn)榭偸强梢酝ㄟ^AS子句給一個(gè)要輸出的字段賦予一個(gè)名稱。
在ORDER BY里還可以使用任意表達(dá)式, 包括那些沒有出現(xiàn)在SELECT輸出列表里面的字段。因此下面的語句現(xiàn)在是合法的:
SELECT name FROM distributors ORDER BY code;
這個(gè)特性的一個(gè)局限就是應(yīng)用于UNION, INTERSECT或EXCEPT查詢的ORDER BY子句 只能在一個(gè)輸出字段名或者數(shù)字上聲明,而不能在一個(gè)表達(dá)式上聲明。
請(qǐng)注意如果一個(gè)ORDER BY表達(dá)式是一個(gè)簡(jiǎn)單名稱, 同時(shí)匹配輸出字段和輸入字段,ORDER BY將把它解釋成輸出字段名稱。 這和GROUP BY在同樣情況下做的選擇正相反。這樣的不一致是由SQL標(biāo)準(zhǔn)強(qiáng)制的。
可以給ORDER BY子句里每個(gè)字段加一個(gè)可選的ASC(升序,缺省) 或DESC(降序)關(guān)鍵字。 還可以在USING子句里聲明一個(gè)排序操作符來實(shí)現(xiàn)排序。 一個(gè)排序操作符必須是一個(gè)小于或者大于一些B-tree操作符的數(shù)量。 ASC等效于使用USING <而DESC等效于使用USING >。 但是一個(gè)用戶定義類型的創(chuàng)建者可以明確定義缺省的排序順序, 并且可以使用其他名稱的操作符。
如果指定NULLS LAT,空值會(huì)在所有非空值之后排序;如果指定 NULLS FIRST,空值會(huì)在所有非空值之前排序。如果兩者均為指定, 當(dāng)指定ASC時(shí),默認(rèn)反應(yīng)時(shí)是NULLS LAST,并且 當(dāng)指定DESC時(shí),默認(rèn)反應(yīng)時(shí)是NULLS FIRST(然而, 默認(rèn)地認(rèn)為空是大于非空的)。當(dāng)指定USING,默認(rèn)空排序時(shí)依賴 操作符是否是一個(gè)更小或者更大的操作符。
請(qǐng)注意排序選項(xiàng)僅適用于他們遵循的表達(dá)式;例如ORDER BY x, y DESC 不意味著與ORDER BY x DESC, y DESC相同。
字符類型的數(shù)據(jù)是按照區(qū)域相關(guān)的字符集順序排序的,這個(gè)區(qū)域是在數(shù)據(jù)庫創(chuàng)建的時(shí)候建立的。
如果聲明了DISTINCT,那么就從結(jié)果集中刪除所有重復(fù)的行 (每個(gè)有重復(fù)的組都保留一行)。 ALL聲明相反的作用:所有行都被保留(這是缺省)。
DISTINCT ON ( expression [, ...] )只 保留那些在給出的表達(dá)式上運(yùn)算出相同結(jié)果的行集合中的第一行。 DISTINCT ON表達(dá)式是使用與ORDER BY 相同的規(guī)則進(jìn)行解釋的。 請(qǐng)注意,除非使用了ORDER BY來保證需要的行首先出現(xiàn),否則, "第一行"是不可預(yù)測(cè)的。比如,
SELECT DISTINCT ON (location) location, time, report FROM weather_reports ORDER BY location, time DESC;
為每個(gè)地點(diǎn)檢索最近的天氣報(bào)告。但是如果沒有使用ORDER BY來強(qiáng)制對(duì)每個(gè)地點(diǎn)的時(shí)間值進(jìn)行降序排序, 那么就會(huì)得到每個(gè)地點(diǎn)的不知道什么時(shí)候的報(bào)告。
DISTINCT ON表達(dá)式必須匹配最左邊的ORDER BY表達(dá)式。 ORDER BY子句將通常包含額外的表達(dá)式來判斷每個(gè)DISTINCT ON 組里面需要的行的優(yōu)先級(jí)。
LIMIT子句由兩個(gè)獨(dú)立的子句組成:
LIMIT { count | ALL } OFFSET start
count聲明返回的最大行數(shù), 而start聲明開始返回行之前忽略的行數(shù)。 如果兩個(gè)都指定了,那么在開始計(jì)算count個(gè)返回行之前將先跳過 start行。
如果count表達(dá)式職位NULL, 它被當(dāng)做LIMIT ALL,也就是,沒有限制。如果 start 評(píng)估為空,他與 OFFSET 0相同對(duì)待。
SQL:2008引入了一個(gè)不同的語法來達(dá)到相同的效果,這也是PostgreSQL 支持的。這是:
OFFSET start { ROW | ROWS } FETCH { FIRST | NEXT } [ count ] { ROW | ROWS } ONLY
根據(jù)該標(biāo)準(zhǔn),OFFSET子句必須在FETCH子句之前 出現(xiàn),若兩個(gè)都存在;但是PostgreSQL的要求更為寬松并且允許兩種順序 中的任意一種。ROW和ROWS以及 FIRST和NEXT是不影響這些子句的效果的干擾詞, 在這個(gè)語法中。在該語法中,當(dāng)使用表達(dá)式而非start 或者count的簡(jiǎn)單常量,圓括號(hào)在大多數(shù) 情況下是有必要的。如果count在FETCH中 省略了,它默認(rèn)為1.
使用LIMIT的一個(gè)好習(xí)慣是使用一個(gè)ORDER BY子句把結(jié)果行限制成一個(gè)唯一的順序。 否則您會(huì)得到無法預(yù)料的結(jié)果子集,您可能想要第十行到第二十行,除非您聲明ORDER BY, 否則您不知道什么順序。
查詢優(yōu)化器在生成查詢規(guī)劃時(shí)會(huì)把LIMIT考慮進(jìn)去, 所以您很有可能因給出的LIMIT和OFFSET值不同而得到不同的規(guī)劃(生成不同的行序)。 因此用不同的LIMIT/OFFSET值選擇不同的查詢結(jié)果的子集將不會(huì)產(chǎn)生一致的結(jié)果, 除非您用ORDER BY強(qiáng)制生成一個(gè)可預(yù)計(jì)的結(jié)果順序。這可不是bug;這是SQL生來的特點(diǎn) ,因?yàn)槌怯昧?tt class="LITERAL">ORDER BY約束順序,SQL不保證查詢生成的結(jié)果有任何特定的順序。
對(duì)于返回表行不同子集的相同LIMIT查詢的重復(fù)執(zhí)行甚至都是可能的, 如果沒有一個(gè)ORDER BY來強(qiáng)制選擇一個(gè)確定性子集。此外,這不是一個(gè) 漏洞;結(jié)果的決定論在這種情況下沒法保證。
FOR UPDATE子句的形式如下:
FOR UPDATE [ OF table_name [, ...] ] [ NOWAIT ]
很相近的FOR SHARE子句的形式如下:
FOR SHARE [ OF table_name [, ...] ] [ NOWAIT ]
FOR UPDATE令那些被SELECT檢索出來的行被鎖住, 就像要更新一樣。這樣就避免它們?cè)诋?dāng)前事務(wù)結(jié)束前被其它事務(wù)修改或者刪除; 也就是說,其它企圖UPDATE, DELETE或SELECT FOR UPDATE這些行的事務(wù)將被阻塞, 直到當(dāng)前事務(wù)結(jié)束。同樣,如果一個(gè)來自其它事務(wù)的UPDATE,DELETE, 或SELECT FOR UPDATE 已經(jīng)鎖住了某個(gè)或某些選定的行,SELECT FOR UPDATE將等到那些事務(wù)結(jié)束,并且將隨后鎖住并返回更新的行(或者不返回行, 如果行已經(jīng)被刪除)。 在一個(gè)SERIALIZABLE事務(wù)內(nèi),然而,若要鎖定的一行已經(jīng)被改變, 一個(gè)錯(cuò)誤將會(huì)在事務(wù)啟動(dòng)后拋出,更多的討論參閱Chapter 13。
FOR SHARE的行為類似,只是它在每個(gè)檢索出來的行上要求一個(gè)共享鎖, 而不是一個(gè)排它鎖。一個(gè)共享鎖阻塞其它事務(wù)在這些行上執(zhí)行 UPDATE,DELETE或SELECT FOR UPDATE卻不阻止他們執(zhí)行SELECT FOR SHARE。
為了避免操作等待其它事務(wù)提交,使用NOWAIT選項(xiàng)。 那么NOWAIT將會(huì)立即匯報(bào)一個(gè)錯(cuò)誤,而不是等待。如果被選擇的行不能立即被鎖住,請(qǐng)注意, NOWAIT只適用于行級(jí)別的鎖,要求的表級(jí)鎖ROW SHARE仍然以通常的方法進(jìn)行 (參閱Chapter 13)。 如果需要申請(qǐng)表級(jí)別的鎖同時(shí)又不等待,那么您可以使用LOCK的 NOWAIT選項(xiàng)。
如果在FOR UPDATE或FOR SHARE中明確指定了表名字, 那么將只有這些指定的表被鎖定,其他在SELECT中使用的表將不會(huì)被鎖定。 一個(gè)其后不帶表列表的FOR UPDATE或FOR SHARE子句將鎖定該命令中所有使用的表。 如果FOR UPDATE或FOR SHARE應(yīng)用于一個(gè)視圖或者子查詢, 它同樣將鎖定所有該視圖或子查詢中使用到的表。 然而,FOR UPDATE/FOR SHARE不適用于 主查詢引用的WITH查詢。如果你想行鎖在一個(gè)WITH查詢內(nèi)發(fā)生, 在WITH查詢內(nèi),指定FOR UPDATE或者 FOR SHARE。
多個(gè)FOR UPDATE和FOR SHARE子句可以用于為不同的表指定不同的鎖定模式。 如果一個(gè)表出同時(shí)出現(xiàn)(或隱含同時(shí)出現(xiàn))在FOR UPDATE和 FOR SHARE子句中,那么將按照FOR UPDATE處理。類似的, 如果影響一個(gè)表的任意子句中出現(xiàn)了NOWAIT,那么該表將按照NOWAIT處理。
FOR UPDATE和FOR SHARE不能在那些無法使用獨(dú)立的表行清晰標(biāo)識(shí)返回行的環(huán)境里; 比如,它不能和聚集一起使用。
當(dāng)FOR UPDATE或者FOR SHARE 出現(xiàn)在SELECT查詢的頂層,鎖住的行通常都是那些查詢返回的; 對(duì)于連接查詢,鎖住的行是那些導(dǎo)致返回連接行的。此外,那些滿足查詢快照中的 查詢條件的行將被鎖住,盡管如果他們?cè)诳煺蘸蟊桓虏⑶也辉贊M足查詢條件, 就不會(huì)再被返回。 如果使用一個(gè)LIMIT,加鎖停止一次就足夠行返回滿足限制(但請(qǐng)注意 通過OFFSET跳過的行將會(huì)加鎖)。如果FOR UPDATE 或者FOR SHARE用于一個(gè)游標(biāo)的查詢,只有通過游標(biāo)實(shí)際讀取或 逐步執(zhí)行的行將會(huì)被鎖住。
當(dāng)FOR UPDATE或者FOR SHARE出現(xiàn)在 SELECT下面,鎖定的行是那些通過子查詢返回到外部查詢的。 這可能涉及到比檢查子查詢時(shí)顯示的更少的行,因?yàn)橥獠坎樵兊臈l件可能會(huì)用來 優(yōu)化子查詢的執(zhí)行。例如:
SELECT * FROM (SELECT * FROM mytable FOR UPDATE) ss WHERE col1 = 5;
將會(huì)鎖定僅擁有col1 = 5的行,即使那個(gè)條件在子查詢中不是 原文的。
Caution |
不要先鎖定一個(gè)行然后在隨后的保存點(diǎn)或PL/pgSQL異常 塊中修改它。因?yàn)槿绻髞砘貪L的話將導(dǎo)致這個(gè)快丟失。例如: BEGIN; SELECT * FROM mytable WHERE key = 1 FOR UPDATE; SAVEPOINT s; UPDATE mytable SET ... WHERE key = 1; ROLLBACK TO s; ROLLBACK之后,該行將被解鎖,而不是返回其上一個(gè)保存點(diǎn)狀態(tài)(被鎖定但未被修改)。 如果一個(gè)在當(dāng)前事務(wù)中鎖定的行被更新或刪除,或者一個(gè)共享鎖被升級(jí)為排它鎖,這種情況就可能會(huì)出現(xiàn)。 在這兩種情況下,先前的鎖狀態(tài)將被遺忘。如果事務(wù)后來回滾到一個(gè)介于最初鎖命令和后來變更了鎖狀態(tài)之間的某個(gè)點(diǎn), 那么該行將表現(xiàn)得好像根本沒有被鎖定一樣。這個(gè)實(shí)現(xiàn)上的缺陷可能在將來的PostgreSQL版本中得到修補(bǔ)。 |
Caution |
一個(gè)SELECT命令可以同時(shí)使用ORDER BY 和FOR UPDATE/SHARE返回行的順序。 這是因?yàn)?tt class="LITERAL">ORDER BY先生效。命令排序結(jié)果,但是可能會(huì)在其中一行 或多行上獲取鎖的時(shí)候被阻塞。但SELECT的阻塞被解除, 一些排序的列值可能已經(jīng)被修改,導(dǎo)致這些行不按順序出現(xiàn)(盡管它們是按初始 列值的順序的)。這個(gè)可以通過必要時(shí)在子查詢中配置 FOR UPDATE/SHARE來進(jìn)行,例如: SELECT * FROM (SELECT * FROM mytable FOR UPDATE) ss ORDER BY column1; 請(qǐng)注意這將導(dǎo)致鎖定mytable的所有行,而頂層的FOR UPDATE 將會(huì)實(shí)際上僅鎖住返回行。這可能會(huì)產(chǎn)生一個(gè)顯著的性能差異,尤其是如果ORDER BY 與LIMIT或者其他限制結(jié)合。僅當(dāng)順序咧的并發(fā)更新是預(yù)期的并且一個(gè)嚴(yán)格的排序結(jié)果 是必須的時(shí),該技術(shù)才是建議使用的。 |
命令
TABLE name
完全等價(jià)于
SELECT * FROM name
它可以用作復(fù)雜查詢中的一部分的一個(gè)頂級(jí)的命令或者一個(gè)節(jié)省空間的語法變體
將表films和表distributors連接在一起:
SELECT f.title, f.did, d.name, f.date_prod, f.kind FROM distributors d, films f WHERE f.did = d.did title | did | name | date_prod | kind -------------------+-----+--------------+------------+---------- The Third Man | 101 | British Lion | 1949-12-23 | Drama The African Queen | 101 | British Lion | 1951-08-11 | Romantic ...
統(tǒng)計(jì)用kind分組的每組電影的長度(len)總和:
SELECT kind, sum(len) AS total FROM films GROUP BY kind; kind | total ----------+------- Action | 07:34 Comedy | 02:58 Drama | 14:28 Musical | 06:42 Romantic | 04:38
統(tǒng)計(jì)用kind分組的每組電影的長度(len )總 和不足五小時(shí)的組:
SELECT kind, sum(len) AS total FROM films GROUP BY kind HAVING sum(len) < interval '5 hours'; kind | total ----------+------- Comedy | 02:58 Romantic | 04:38
下面兩個(gè)例子是根據(jù)第二列(name)的內(nèi)容對(duì)單獨(dú)的結(jié)果排序的經(jīng)典的方法:
SELECT * FROM distributors ORDER BY name; SELECT * FROM distributors ORDER BY 2; did | name -----+------------------ 109 | 20th Century Fox 110 | Bavaria Atelier 101 | British Lion 107 | Columbia 102 | Jean Luc Godard 113 | Luso films 104 | Mosfilm 103 | Paramount 106 | Toho 105 | United Artists 111 | Walt Disney 112 | Warner Bros. 108 | Westward
下面這個(gè)例子演示如何獲得表distributors和actors 的連接,只將每個(gè)表中以字母W開頭的取出來。因?yàn)橹蝗×瞬恢貜?fù)的行,所以關(guān)鍵字 ALL被省略了:
distributors: actors: did | name id | name -----+-------------- ----+---------------- 108 | Westward 1 | Woody Allen 111 | Walt Disney 2 | Warren Beatty 112 | Warner Bros. 3 | Walter Matthau ... ... SELECT distributors.name FROM distributors WHERE distributors.name LIKE 'W%' UNION SELECT actors.name FROM actors WHERE actors.name LIKE 'W%'; name ---------------- Walt Disney Walter Matthau Warner Bros. Warren Beatty Westward Woody Allen
這個(gè)例子顯示了如何在FROM子句中使用函數(shù),包括帶有和不帶字段定義列表的。
CREATE FUNCTION distributors(int) RETURNS SETOF distributors AS $$ SELECT * FROM distributors WHERE did = $1; $$ LANGUAGE SQL; SELECT * FROM distributors(111); did | name -----+------------- 111 | Walt Disney CREATE FUNCTION distributors_2(int) RETURNS SETOF record AS $$ SELECT * FROM distributors WHERE did = $1; $$ LANGUAGE SQL; SELECT * FROM distributors_2(111) AS (f1 int, f2 text); f1 | f2 -----+------------- 111 | Walt Disney
這個(gè)例子展示了如何使用一個(gè)簡(jiǎn)單的WITH子句:
WITH t AS ( SELECT random() as x FROM generate_series(1, 3) ) SELECT * FROM t UNION ALL SELECT * FROM t x -------------------- 0.534150459803641 0.520092216785997 0.0735620250925422 0.534150459803641 0.520092216785997 0.0735620250925422
請(qǐng)注意WITH查詢僅評(píng)估一次,所以我們得到相同的三個(gè)隨機(jī)值的 兩個(gè)集合。
該示例使用WITH RECURSIVE來找到雇主Mary的所有下屬 (直接或者間接),以及他們的間接級(jí)別,從一個(gè)僅顯示直接下屬的表:
WITH RECURSIVE employee_recursive(distance, employee_name, manager_name) AS ( SELECT 1, employee_name, manager_name FROM employee WHERE manager_name = 'Mary' UNION ALL SELECT er.distance + 1, e.employee_name, e.manager_name FROM employee_recursive er, employee e WHERE er.employee_name = e.manager_name ) SELECT distance, employee_name FROM employee_recursive;
注意遞歸查詢的典型形式:一個(gè)初始條件,緊接著是UNION, 然后是查詢的遞歸部分。確定查詢的遞歸部分最終將不會(huì)返回元組,否則 查詢將循環(huán)下去。(請(qǐng)參閱Section 7.8獲取更多示例)
SELECT語句和SQL標(biāo)準(zhǔn)兼容。但是還有一些擴(kuò)展和一些缺少的特性。
PostgreSQL允許在一個(gè)查詢里省略FROM子句。 它的最直接用途就是計(jì)算簡(jiǎn)單的常量表達(dá)式的結(jié)果:
SELECT 2+2; ?column? ---------- 4
其它有些SQL數(shù)據(jù)庫不能這么做,除非引入一個(gè)單行的偽表做為 SELECT的數(shù)據(jù)源。
請(qǐng)注意,如果沒有聲明FROM子句,那么查詢不能引用任何數(shù)據(jù)庫表。 比如,下面的查詢是非法的:
SELECT distributors.* WHERE distributors.name = 'Westward';
PostgreSQL8.1之前的版本支持這種形式的查詢, 為查詢里引用的每個(gè)表都增加一個(gè)隱含的條目到FROM子句中?,F(xiàn)在這個(gè)不再是缺省的了。
在SQL標(biāo)準(zhǔn)中,每當(dāng)新列名稱是一個(gè)有效的列名時(shí),可選的關(guān)鍵字 AS可以在輸出列名之前省略(也即,不是跟任何保留關(guān)鍵字都相同的)。 PostgreSQL限制略多一些:不管是保留還是不保留, 如果新列名匹配任何關(guān)鍵字,AS是必要的。建議的做法是使用AS 或者雙括號(hào)括起輸出列名稱,以阻止對(duì)將來的關(guān)鍵字補(bǔ)充的任何可能的沖突。
在FROM項(xiàng)中,標(biāo)準(zhǔn)和 PostgreSQL 都允許AS在一個(gè)無限制關(guān)鍵字別名之前省略。但是這對(duì)輸出列名 是不切實(shí)際的, 因?yàn)檎Z法的含糊不清。
SQL標(biāo)準(zhǔn)需要括號(hào)括起ONLY之后的表名,如同與SELECT * FROM ONLY (tab1), ONLY (tab2) WHERE ...。PostgreSQL也支持哪些,但是括號(hào)是可選的。 (該點(diǎn)同樣適用于所有支持ONLY選項(xiàng)的SQL命令。)
在SQL-92標(biāo)準(zhǔn)里,ORDER BY子句只能使用輸出字段名或者編號(hào), 而GROUP BY子句只能用基于輸入字段名的表達(dá)式。PostgreSQL對(duì)這兩個(gè)子句都進(jìn)行了擴(kuò)展, 允許另外一種選擇(但是如果存在歧義,則使用標(biāo)準(zhǔn)的解釋)。PostgreSQL還允許兩個(gè)子句聲明任意的表達(dá)式。 請(qǐng)注意在表達(dá)式中出現(xiàn)的名字總是被當(dāng)作輸入字段名,而不是輸出字段名。
SQL:1999以及之后的一個(gè)略微不同的定義并不能和SQL-92完全向前兼容。 不過,在大多數(shù)情況下,PostgreSQL將把 一個(gè)ORDER BY或GROUP BY表達(dá)式解析成為SQL:1999制定的那樣。
SQL標(biāo)準(zhǔn)提供了窗口frame_clause的 附加選項(xiàng)。 PostgreSQL目前僅支持上面列出的選項(xiàng)。
語句LIMIT和OFFSET是特定的 PostgreSQL語法,也是MySQL 使用的。SQL:2008標(biāo)準(zhǔn)引入了OFFSET ... FETCH {FIRST|NEXT} ...獲取相同的功能性,如上面LIMIT子句 所示。該語法也被IBM DB2使用。(為Oracle 所寫的應(yīng)用程序通常使用一個(gè)涉及自動(dòng)生成的rownum列的工作區(qū), 要實(shí)現(xiàn)這些子句的效果,這在PostgreSQL中是不可用的。)
盡管FOR UPDATE出現(xiàn)在SQL標(biāo)準(zhǔn)中,該標(biāo)準(zhǔn)允許它只是作為 DECLARE CURSOR的一個(gè)選項(xiàng)。PostgreSQL 允許它在人惡化SELECT查詢以及SELECT子查詢中, 但這是一個(gè)擴(kuò)展。FOR SHARE變體以及NOWAIT選項(xiàng), 不出現(xiàn)在標(biāo)準(zhǔn)中。
DISTINCT ON子句都沒有在SQL標(biāo)準(zhǔn)中定義。