<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                # SELECT ## Name SELECT, TABLE, WITH?--?從表或視圖中取出若干行 ## Synopsis ``` [ 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 | DISTINCT ] _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 | NO KEY UPDATE | SHARE | KEY SHARE } [ OF _table_name_ [, ...] ] [ NOWAIT ] [...] ] 這里的`_from_item_` 可以是: [ ONLY ] _table_name_ [ * ] [ [ AS ] _alias_ [ ( _column_alias_ [, ...] ) ] ] [ LATERAL ] ( _select_ ) [ AS ] _alias_ [ ( _column_alias_ [, ...] ) ] _with_query_name_ [ [ AS ] _alias_ [ ( _column_alias_ [, ...] ) ] ] [ LATERAL ] _function_name_ ( [ _argument_ [, ...] ] ) [ AS ] _alias_ [ ( _column_alias_ [, ...] | _column_definition_ [, ...] ) ] [ LATERAL ] _function_name_ ( [ _argument_ [, ...] ] ) AS ( _column_definition_ [, ...] ) _from_item_ [ NATURAL ] _join_type_ _from_item_ [ ON _join_condition_ | USING ( _join_column_ [, ...] ) ] `_with_query_`是: _with_query_name_ [ ( _column_name_ [, ...] ) ] AS ( _select_ | _values_ | _insert_ | _update_ | _delete_ ) TABLE [ ONLY ] _table_name_ [ * ] ``` ## 描述 `SELECT`將從零個或更多表中返回記錄行。`SELECT`通常的處理如下: 1. 計算列出在`WITH`中的所有查詢。這些有效的充當可以在 `FROM`列表中引用的臨時表。一個在`FROM` 中多次引用的`WITH`查詢只計算一次。(參閱下面的 [_WITH_ 子句](#calibre_link-1320)。) 2. 計算列出在`FROM`中的所有元素(`FROM` 列表中的每個元素都是一個實際的或虛擬的表)。如果在`FROM` 列表里聲明了多個元素,那么他們就交叉連接在一起(參見下面的 [_FROM_ 子句](#calibre_link-516))。 3. 如果聲明了`WHERE`子句,那么在輸出中消除所有不滿足條件的行。 (參見下面的[_WHERE_ 子句](#calibre_link-1321)。) 4. 如果聲明了`GROUP BY`子句,輸出就組合成匹配一個或多個數值的不同組里。 如果出現了`HAVING`子句,那么它消除那些不滿足給出條件的組。 (參見下面的[_GROUP BY_ 子句](#calibre_link-1322) 和 [_HAVING_ 子句](#calibre_link-1323)。) 5. 實際輸出行將使用`SELECT`輸出表達式針對每一個選中的行或行組進行計算。 (參見下面的[_SELECT_ 列表](#calibre_link-1324)。) 6. `SELECT DISTINCT`從結果中消除重復的行。`SELECT DISTINCT ON` 消除匹配所有指定表達式的行。`SELECT ALL`(缺省)返回所有的行, 包括重復的行。(參閱下面的[_DISTINCT_ 子句](#calibre_link-1325)。) 7. 使用`UNION`, `INTERSECT`, `EXCEPT` 可以把多個`SELECT`語句的輸出合并成一個結果集。`UNION` 操作符返回兩個結果集的并集。`INTERSECT`操作符返回兩個結果集的交集。 `EXCEPT`操作符返回在第一個結果集對第二個結果集的差集。不管哪種情況, 重復的行都被刪除,除非聲明了`ALL`。噪聲字`DISTINCT` 可以用來明確的聲明消除重復的行。請注意,`DISTINCT`在這里是缺省的行為, 即使`ALL`是`SELECT`本身的缺省。 (參閱下面的[_UNION_ 子句](#calibre_link-1326)、[_INTERSECT_ 子句](#calibre_link-1327)、 [_EXCEPT_ 子句](#calibre_link-1328)。) 8. 如果聲明了`ORDER BY`子句,那么返回的行將按照指定的順序排序。 如果沒有給出`ORDER BY`,那么數據行是按照系統認為可以最快生成的順序給出的。 (參閱下面的[_ORDER BY_ 子句](#calibre_link-1329)。) 9. 如果給出了`LIMIT`(或 `FETCH FIRST`)或 `OFFSET`子句,那么`SELECT`語句只返回結果行的一個子集。 (參閱下面的[_LIMIT_ 子句](#calibre_link-1059)。) 10. 如果聲明了`FOR UPDATE`, `FOR NO KEY UPDATE`, `FOR SHARE` 或`FOR KEY SHARE`子句,那么`SELECT`語句對并發的更新鎖住選定的行。 (參閱下面的[_鎖定子句_](#calibre_link-1058)子句。) 你必須對每個在`SELECT`命令中使用的字段有`SELECT`權限。 使用`FOR NO KEY UPDATE`, `FOR UPDATE`, `FOR SHARE` 或`FOR KEY SHARE`還要求`UPDATE`權限 (至少選擇每個表的一列)。 ## 參數 ### `WITH` 子句 `WITH`子句允許聲明一個或多個可以在主查詢中通過名字引用的子查詢。 子查詢在主查詢期間有效的充當臨時表或視圖。每個子查詢可以是`SELECT`, `VALUES`, `INSERT`, `UPDATE` 或 `DELETE`語句。當在`WITH`中寫一個數據修改語句時 (`INSERT`, `UPDATE` 或 `DELETE`), 通常包含一個`RETURNING`子句。`RETURNING`的輸出而_不是_ 語句修改的底層表的輸出形成被主查詢讀取的臨時表。如果省略了`RETURNING`, 該語句仍然執行,但是不會產生輸出,所以不能作為一個表被主查詢引用。 必須為每個`WITH`查詢聲明一個名字(沒有模式修飾)。 可選的,可以指定字段名的列表;如果省略了,那么字段名從子查詢中推斷出。 如果聲明了`RECURSIVE`,那么允許`SELECT`子查詢通過名字引用它自己。 比如一個有下面形式的子查詢 ``` _non_recursive_term_ UNION [ ALL | DISTINCT ] _recursive_term_ ``` 遞歸的自我引用必須在`UNION`的右邊出現。每個查詢只允許一個遞歸的自我引用。 不支持遞歸的數據修改語句,但是可以在數據修改語句中使用遞歸的`SELECT` 查詢的結果。參閱[Section 7.8](#calibre_link-515)獲取一個例子。 `RECURSIVE`的另外一個作用是`WITH`查詢不需要排序: 一個查詢可以引用另外一個稍后出現在列表中的查詢。(但是,循環引用或相互遞歸沒有實現。) 沒有`RECURSIVE`,`WITH`查詢只能引用 更早出現在`WITH`列表中的同層級的`WITH`查詢。 `WITH`查詢的主要特性是他們只在主查詢的每次執行中評估一次, 即使主查詢引用了他們多次也是如此。特別的,保證數據修改語句只被執行一次, 不管主查詢讀取他們的所有或任意的輸出。 主查詢和`WITH`查詢(理論上)同時執行。這意味著`WITH` 中的數據修改語句的影響不能從查詢的其他部分看到,除非讀取它的`RETURNING` 輸出。如果兩個這樣的數據修改語句嘗試修改相同的行,那么結果是未知的。 參閱[Section 7.8](#calibre_link-515)獲取額外的信息。 ### `FROM` 子句 `FROM`子句為`SELECT`聲明一個或者多個源表。如果聲明了多個源表, 那么結果就是所有源表的笛卡兒積(交叉連接)。但是通常會添加一些條件(通過`WHERE`), 把返回行限制成笛卡兒積的一個小的子集。 `FROM`子句可以包括下列元素: `_table_name_` 一個現存的表或視圖的名字(可以有模式修飾)。如果聲明了`ONLY`,則只掃描該表; 否則,該表和所有其派生表(如果有的話)都被掃描。可以在表名后面跟一個`*` 表示掃描所有其后代表。 `_alias_` 為那些包含別名的`FROM`項目取的別名。別名用于縮寫或者在自連接中消除歧義 (自連接中同一個表將掃描多次)。如果提供了別名,那么它就會完全隱藏表或者函數的實際名字; 比如,如果給出`FROM foo AS f`,那么`SELECT` 剩下的東西必須把這個`FROM`項按照`f`而不是`foo`引用。 如果寫了別名,也可以提供一個字段別名列表,這樣可以替換表中一個或者多個字段的名字。 `_select_` 可以在`FROM`子句里出現一個子`SELECT`。 它的輸出作用好像是為這條`SELECT`命令在其生存期里創建一個臨時表。 請注意這個子`SELECT`必須用園括弧包圍。并且_必須_給它一個別名。 當然,[VALUES](#calibre_link-106)同樣也可以在這里使用。 `_with_query_name_` `WITH`查詢通過寫它自己的名字來引用,就像查詢的名字就是一個表的名字。 (實際上,`WITH`查詢為主查詢隱藏了相同名字的任意實際表。 如果需要,可以通過模式限定表的名字來引用相同名字的實際表。)別名可以用相同的方式提供給表。 `_function_name_` 函數(特別是那些返回結果集的函數)調用可以出現在`FROM`子句里。 這么做就好像在這個`SELECT`命令的生命期中,把函數的輸出創建為一個臨時表一樣。 當然也可以使用別名。如果寫了別名,還可以寫一個字段別名列表, 為函數返回的復合類型的一個或多個屬性提供名字替換。如果函數定義為返回`record`類型, 那么必須出現一個`AS`關鍵字或者別名,后面跟著一個形如 `(` `_column_name_` `_data_type_` [, ... ] )的字段定義列表。這個字段定義列表必須匹配函數返回的字段的實際數目和類型。 `_join_type_` 下列之一: * `[ INNER ] JOIN` * `LEFT [ OUTER ] JOIN` * `RIGHT [ OUTER ] JOIN` * `FULL [ OUTER ] JOIN` * `CROSS JOIN` 必須為`INNER`和`OUTER`連接類型聲明一個連接條件, 也就是`NATURAL`, `ON` `_join_condition_`, or `USING (``_join_column_` [, ...]) 之一。 它們的含義見下文,對于`CROSS JOIN`而言,這些子句都不能出現。 一個`JOIN`子句組合兩個`FROM`項,為了方便我們將其作為"tables" 引用,盡管實際上他們可以是任意`FROM`條目的類型。必要時使用圓括弧以決定嵌套的順序。 如果沒有圓括弧,`JOIN`從左向右嵌套。在任何情況下,`JOIN` 都比逗號分隔的`FROM`列表綁定得更緊。 `CROSS JOIN`和`INNER JOIN`生成一個簡單的笛卡兒積, 和你在`FROM`的頂層列出兩個表的結果相同,但是受到連接條件(如果有)的限制。 `CROSS JOIN`等效于`INNER JOIN ON (TRUE)`,也就是說, 沒有被條件刪除的行。這種連接類型只是符號上的方便,因為它們和你用簡單的 `FROM`和`WHERE`的效果一樣。 `LEFT OUTER JOIN`返回笛卡兒積中所有符合連接條件的行, 再加上左表中通過連接條件沒有匹配右表行的那些行。這樣,左邊的行將擴展成生成表的全長, 方法是在那些右表對應的字段位置填上 NULL 。請注意,只在計算匹配的時候, 才使用`JOIN`子句的條件,外層的條件是在計算完畢之后施加的。 相應的,`RIGHT OUTER JOIN`返回所有內連接的結果行, 加上每個不匹配的右邊行(左邊用 NULL 擴展)。這只是一個符號上的便利, 因為總是可以把它轉換成一個`LEFT OUTER JOIN`,只要把左邊和右邊的輸入對掉一下即可。 `FULL OUTER JOIN`返回所有內連接的結果行,加上每個不匹配的左邊行(右邊用 NULL 擴展), 再加上每個不匹配的右邊行(左邊用 NULL 擴展)。 `ON` `_join_condition_` 一個生成`boolean`類型結果的表達式(類似`WHERE`子句), 限定連接中那些行是匹配的。 `USING (` `_join_column_` [, ...] ) 一個形如`USING ( a, b, ... )` 的子句,是`ON left_table.a = right_table.a AND left_table.b = right_table.b ...`的縮寫。 同樣,`USING`蘊涵著每對等效字段中只有一個包含在連接輸出中,而不是兩個都輸出的意思。 `NATURAL` `NATURAL`是一個`USING`列表的縮寫,這個列表說的是兩個表中同名的字段。 `LATERAL` `LATERAL`關鍵字可以放在一個子`SELECT` `FROM`項目的前面。 這允許子`SELECT`引用出現在`FROM`列表之前的`FROM`條目中的字段。 (沒有`LATERAL`,每個子`SELECT`獨立評估并且以此不能交叉引用任何其他 `FROM`條目。) `LATERAL`也可以放在一個函數調用`FROM`條目的前面, 但是這種情況下它是一個噪聲字,因為函數表達式可以在任何情況下引用前面的`FROM`條目。 `LATERAL`可以出現在`FROM`列表的頂層,或出現在`JOIN`樹中。 在后面當前情況下,它也可以引用`JOIN`左側和右側的任意條目。 當`FROM`條目包含`LATERAL`交叉引用時,評估收益如下: 對于提供交叉引用字段的`FROM`條目的每一行,或提供字段的多個`FROM` 條目的行集,使用該字段的行或行集值評估`LATERAL`條目。 結果行像往常一樣和計算他們的行連接。這是從字段源表重復每行或行集。 字段源表必須`INNER`或`LEFT`連接`LATERAL`條目, 其他為`LATERAL`條目計算每個行集的行集將不會是明確定義的行集。 因此,盡管一個構造(如`_X_` RIGHT JOIN LATERAL `_Y_`) 在語法結構上合法,并不實際上允許`_Y_`引用`_X_`。 ### `WHERE` 子句 可選的`WHERE`條件有如下常見的形式: ``` WHERE _condition_ ``` 這里`_condition_`可以是任意生成類型為 `boolean`的表達式。任何不滿足這個條件的行都會從輸出中刪除。 如果一個行的數值代入到條件中計算出來的結果為真,那么該行就算滿足條件。 ### `GROUP BY` 子句 可選的`GROUP BY`子句的一般形式 ``` GROUP BY _expression_ [, ...] ``` 它將把所有在組合表達式上擁有相同值的行壓縮成一行。 `_expression_`可以是一個輸入字段名字, 或者是一個輸出字段(`SELECT`列表項)的名字或序號, 或者也可以是任意輸入字段組成的表達式。在有歧義的情況下, 一個`GROUP BY`的名字將被解釋成輸入字段的名字,而不是輸出字段的名字。 如果使用了聚集函數,那么就會對每組中的所有行進行計算并生成一個單獨的值 (而如果沒有`GROUP BY`,那么聚集將對選出來的所有行計算出一個單獨的值)。 如果出現了`GROUP BY`,那么`SELECT` 列表表達式中再引用那些沒有分組的字段就是非法的,除非放在聚集函數里, 或未分組的字段函數上依賴于分組的字段,因為對于未分組的字段,可能會返回多個數值。 如果分組的字段(或它們的一個子集)是包含未分組字段的表的主鍵,那么存在一個函數依賴。 ### `HAVING` 子句 可選的`HAVING`子句有如下形式: ``` HAVING _condition_ ``` 這里`_condition_`與為 `WHERE`子句里聲明的相同。 `HAVING`去除了一些不滿足條件的組行。它與`WHERE` 不同:`WHERE`在使用`GROUP BY`之前過濾出單獨的行, 而`HAVING`過濾由`GROUP BY`創建的行。 在`_condition_` 里引用的每個字段都必須無歧義地引用一個分組的行,除非引用出現在一個聚集函數里。 `HAVING`的出現把查詢變成一個分組的查詢,即使沒有`GROUP BY` 子句也這樣。這一點和那些包含聚集函數但沒有`GROUP BY`子句的查詢里發生的事情是一樣的。 所有選取的行都被認為會形成一個單一的組,而`SELECT` 列表和`HAVING`子句只能從聚集函數里面引用表的字段。 這樣的查詢在`HAVING`條件為真的時候將發出一個行,如果為非真,則返回零行。 ### `WINDOW` 子句 `WINDOW`子句的一般形式是 ``` WINDOW _window_name_ AS ( _window_definition_ ) [, ...] ``` 這里的`_window_name_`是可以在`OVER` 子句中引用的名字或隨后的窗口定義,這里的`_window_definition_`是 ``` [ _existing_window_name_ ] [ PARTITION BY _expression_ [, ...] ] [ ORDER BY _expression_ [ ASC | DESC | USING _operator_ ] [ NULLS { FIRST | LAST } ] [, ...] ] [ _frame_clause_ ] ``` 如果聲明了`_existing_window_name_`, 那么必須引用一個在`WINDOW`列表中出現的更早的項;新的窗口從這個項中拷貝分區子句, 和排序子句(如果有)。在這種情況下,這個新的窗口不能聲明他自己的`PARTITION BY`子句, 但是如果拷貝的窗口沒有排序子句的話他可以聲明`ORDER BY`子句。 新窗口總是使用他自己的框架子句;拷貝的窗口必須不能聲明框架子句。 `PARTITION BY`列表的元素的以與[_GROUP BY_ 子句](#calibre_link-1322) 的元素相同的方式來解釋,除了他們總是簡單的表達式并且從不是一個輸出列的名稱或者編號。 另外一個差異是這些表達式可以包含聚集函數調用,而在常規的`GROUP BY`子句中這是不允許的。 在這里允許是因為開窗在分組和聚集之后發生。 同樣的,`ORDER BY`列表的元素以與[_ORDER BY_ 子句](#calibre_link-1329) 的元素相同的方式來解釋,除了這個表達式總是作為簡單的表達式并且從不是一個輸出列的名稱或者編號。 可選的`_frame_clause_`為依賴于框架的窗口函數(不是所有)定義 _窗口框架_。窗口框架是查詢中的每行(稱為_當前行_)的一組相關行。 `_frame_clause_`可以是下列之一 ``` [ RANGE | ROWS ] _frame_start_ [ RANGE | ROWS ] BETWEEN _frame_start_ AND _frame_end_ ``` 這里的`_frame_start_`和`_frame_end_`可以是下列之一 ``` UNBOUNDED PRECEDING _value_ PRECEDING CURRENT ROW _value_ FOLLOWING UNBOUNDED FOLLOWING ``` 如果省略了`_frame_end_`,那么它的缺省是`CURRENT ROW`。 限制是`_frame_start_`不能是`UNBOUNDED FOLLOWING`, `_frame_end_`不能是`UNBOUNDED PRECEDING`, `_frame_end_`選項在上面的列表中不能比`_frame_start_` 選項出現的早,例如`RANGE BETWEEN CURRENT ROW AND` `_value_` PRECEDING是不允許的。 缺省框架選項是`RANGE UNBOUNDED PRECEDING`,這與`RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW`相同;它將框架設置為分區中的所有行,在`ORDER BY` 序列中是從當前行的最后一個元素開始(這意味著若無`ORDER BY`則是所有行)。 通常,`UNBOUNDED PRECEDING`表示框架從分區的第一行開始,類似的 `UNBOUNDED FOLLOWING`表示框架以分區的最后一行結束(不管是`RANGE` 還是`ROWS`模式)。在`ROWS`模式,`CURRENT ROW` 意味著框架以當前行開始或結束;但是在`RANGE`模式,意味著框架以當前行在 `ORDER BY`序列中的第一個或最后一個元素開始或結束。`_value_` `PRECEDING` 和`_value_` `FOLLOWING`子句目前只允許在`ROWS`模式。 他們表明框架以當前行之前或者之后許多行開始或者結束。`_value_` 必須是一個不包含任何變量、聚集函數或者窗口函數的整型表達式。該值不能為空或者負值; 但可以為0,并且這時選擇當前行本身。 注意如果`ORDER BY`排序不能唯一地排列行,那么`ROWS` 選項可能產生不可預測的結果。`RANGE`選項是為了確保`ORDER BY` 序列中的對等的行能得到同等對待;任何兩個對等行將會都在或者都不在框架中。 一個`WINDOW`語句的目的是指定出現在查詢的[_SELECT_ 列表](#calibre_link-1324) 或者[_ORDER BY_ 子句](#calibre_link-1329)中的_window 函數_的行為。 這些函數可以在其`OVER`子句中通過名稱引用`WINDOW`子句條目。 一個`WINDOW`子句條目不需要在任何地方都引用;若它不在查詢中使用,它將被忽略。 可以使用窗口程序而根本不需要任何`WINDOW`子句, 因為一個窗口函數調用可以直接在其`OVER`子句中指定其窗口定義。然而, `WINDOW`子句會在多個窗口函數需要相同窗口定義時保存輸入。 窗口函數在[Section 3.5](#calibre_link-1330), [Section 4.2.8](#calibre_link-1331), 和 [Section 7.2.4](#calibre_link-1332)中有詳細描述。 ### `SELECT` 列表 `SELECT`列表(在`SELECT`和`FROM`關鍵字之間的部分) 聲明組成`SELECT`語句的輸出行的表達式。這些表達式可以 (并且通常也會)引用在`FROM`子句里面計算出來的字段。 就像在一個表中,一個`SELECT`的每個輸出列都有一個名稱。 在一個簡單的`SELECT`中,該名稱僅用于標記顯示的列, 但當`SELECT`是一個較大查詢的子查詢時,名稱被較大查詢視為子查詢產生的虛表的字段名。 為了指定用于輸出列的名稱,要在列表達式后寫`AS` `_output_name_`。(您可以省略`AS`, 但只有當所需的輸出名稱不匹配任何PostgreSQL關鍵字時 (請參閱[Appendix C](#calibre_link-126))。為了防止將來可能的關鍵字添加, 建議您要么寫`AS`要么用雙引號引起輸出名稱。)如果你不指定一個字段名, PostgreSQL會自動選擇一個名稱。如果字段的表達式是一個簡單的列引用, 那么選擇的名稱與字段名相同;在更復雜的情況下,可能會使用一個函數或類型名, 或系統會依賴于一個類似`?column?`的生成名。 一個輸出列的名稱可以用來參考`ORDER BY`和`GROUP BY`子句中的字段的值, 而不是在`WHERE`或者`HAVING`子句中的;反而您必須在那里寫出表達式。 除了表達式,也可以在輸出列表中使用`*`表示所有字段。 還可以用`_table_name_`.* 作為來自該表的所有字段的縮寫。這些情況下用`AS`指定新名稱是不可能的; 輸出列的名稱將會與表列的名稱相同。 ### `DISTINCT` 子句 如果聲明了`SELECT DISTINCT`,那么就從結果集中刪除所有重復的行 (每個有重復的組都保留一行)。`SELECT ALL`聲明相反的作用:所有行都被保留(這是缺省)。 `SELECT DISTINCT ON (` `_expression_` [, ...] ) 只保留那些在給出的表達式上運算出相同結果的行集合中的第一行。`DISTINCT ON` 表達式是使用與`ORDER BY`相同的規則進行解釋的(見上文)。請注意, 除非使用了`ORDER BY`來保證需要的行首先出現,否則,"第一行" 是不可預測的。比如: ``` SELECT DISTINCT ON (location) location, time, report FROM weather_reports ORDER BY location, time DESC; ``` 為每個地點檢索最近的天氣報告。但是如果沒有使用`ORDER BY` 來強制對每個地點的時間值進行降序排序,那么就會得到每個地點的不知道什么時候的報告。 `DISTINCT ON`表達式必須匹配最左邊的`ORDER BY`表達式。 `ORDER BY`子句將通常包含額外的表達式來判斷每個`DISTINCT ON` 組里面需要的行的優先級。 ### `UNION` 子句 `UNION`子句的一般形式是: ``` _select_statement_ UNION [ ALL | DISTINCT ] _select_statement_ ``` 這里的`_select_statement_`是任意沒有 `ORDER BY`, `LIMIT`, `FOR NO KEY UPDATE`, `FOR UPDATE`, `FOR SHARE`, 或 `FOR KEY SHARE`子句的`SELECT`語句。 如果用圓括弧包圍,`ORDER BY`和`LIMIT`可以附著在子表達式里。 如果沒有圓括弧,這些子句將交給`UNION`的結果使用,而不是給它們右邊的輸入表達式。 `UNION`操作符計算那些涉及到的所有`SELECT` 語句返回的行的結果聯合。一個行如果至少在兩個結果集中的一個里面出現, 那么它就會在這兩個結果集的集合聯合中。兩個作為`UNION` 直接操作數的`SELECT`必須生成相同數目的字段, 并且對應的字段必須有兼容的數據類型。 缺省的`UNION`結果不包含任何重復的行,除非聲明了`ALL`選項。 `ALL`制止了消除重復的動作。因此,`UNION ALL`通常比 `UNION`明顯要快,可能的情況下盡量使用`ALL`。 `DISTINCT`可以明確的指定消除重復行的缺省行為。 同一個`SELECT`語句中的多個`UNION`操作符是從左向右計算的, 除非用圓括弧進行了標識。 目前,`FOR NO KEY UPDATE`, `FOR UPDATE`, `FOR SHARE` 和 `FOR KEY SHARE`不能在`UNION`的結果或輸入中聲明。 ### `INTERSECT` 子句 `INTERSECT`子句的一般形式是: ``` _select_statement_ INTERSECT [ ALL | DISTINCT ] _select_statement_ ``` `_select_statement_`是任何不帶 `ORDER BY`, `LIMIT`, `FOR NO KEY UPDATE`, `FOR UPDATE`, `FOR SHARE`, 或 `FOR KEY SHARE`子句的`SELECT`語句。 `INTERSECT`計算涉及的`SELECT`語句返回的行集合的交集。 如果一個行在兩個結果集中都出現,那么它就在兩個結果集的交集中。 `INTERSECT`的結果不包含任何重復行,除非你聲明了`ALL`選項。 用了`ALL`以后,一個在左邊的表里有`_m_`個重復而在右邊表里有 `_n_`個重復的行將在結果集中出現min(`_m_`,`_n_`)次。 `DISTINCT`可以明確的指定消除重復行的缺省行為。 除非用圓括號指明順序,同一個`SELECT`語句中的多個 `INTERSECT`操作符是從左向右計算的。`INTERSECT` 比`UNION`綁定得更緊,也就是說`A UNION B INTERSECT C` 將理解成 `A UNION (B INTERSECT C)`。 目前,不能給`INTERSECT`的結果或者任何`INTERSECT`的輸入聲明 `FOR NO KEY UPDATE`, `FOR UPDATE`, `FOR SHARE` 和 `FOR KEY SHARE`。 ### `EXCEPT` 子句 `EXCEPT`子句有如下的通用形式: ``` _select_statement_ EXCEPT [ ALL | DISTINCT ] _select_statement_ ``` `_select_statement_`是任何沒有 `ORDER BY`, `LIMIT`, `FOR NO KEY UPDATE`, `FOR UPDATE`, `FOR SHARE`, 或 `FOR KEY SHARE`子句的`SELECT`表達式。 `EXCEPT`操作符計算存在于左邊`SELECT` 語句的輸出而不存在于右邊`SELECT`語句輸出的行。 `EXCEPT`的結果不包含任何重復的行,除非聲明了`ALL`選項。 使用`ALL`時,一個在左邊表中有`_m_`個重復而在右邊表中有 `_n_`個重復的行將在結果中出現max(`_m_`-`_n_`,0)次。 `DISTINCT`可以明確的指定消除重復行的缺省行為。 除非用圓括弧指明順序,否則同一個`SELECT`語句中的多個 `EXCEPT`操作符是從左向右計算的。`EXCEPT` 和`UNION`的綁定級別相同。 目前,不能給`EXCEPT`的結果或者任何`EXCEPT`的輸入聲明 `FOR NO KEY UPDATE`, `FOR UPDATE`, `FOR SHARE` 和 `FOR KEY SHARE`子句。 ### `ORDER BY` 子句 可選的`ORDER BY`子句有下面的一般形式: ``` ORDER BY _expression_ [ ASC | DESC | USING _operator_ ] [ NULLS { FIRST | LAST } ] [, ...] ``` `ORDER BY`子句導致結果行根據指定的表達式進行排序。 如果根據最左邊的表達式,兩行的結果相同,那么就根據下一個表達式進行比較, 依此類推。如果對于所有聲明的表達式他們都相同,那么按隨機順序返回。 每個`_expression_`可以是一個輸出字段 (`SELECT`列表項)的名字或者序號,或者也可以是用輸入字段的數值組成的任意表達式。 序數指的是輸出字段按順序(從左到右)的位置。這個特性可以對沒有唯一名稱的字段進行排序。 這不是必須的,因為總是可以通過`AS`子句給一個要輸出的字段賦予一個名稱。 在`ORDER BY`里還可以使用任意表達式,包括那些沒有出現在 `SELECT`輸出列表里面的字段。因此下面的語句現在是合法的: ``` SELECT name FROM distributors ORDER BY code; ``` 這個特性的一個局限就是應用于`UNION`,`INTERSECT`,`EXCEPT` 子句的結果的`ORDER BY`子句只能在一個輸出字段名或者數字上聲明, 而不能在一個表達式上聲明。 如果一個`ORDER BY`表達式是一個簡單名稱,同時匹配結果字段和輸入字段, `ORDER BY`將把它解釋成結果字段名稱。這和`GROUP BY` 在同樣情況下做的選擇正相反。這樣的不一致是用來和 SQL 標準兼容的。 可以給`ORDER BY`子句里每個字段加一個可選的`ASC`(升序,缺省) 或`DESC`(降序)關鍵字。還可以在`USING` 子句里聲明一個排序操作符來實現排序。排序操作符必須小于或大于某些B-tree操作符族的成員。 `ASC`等效于使用`USING &lt;`而`DESC`等效于使用`USING &gt;`。 但是一個用戶定義類型的創建者可以明確定義缺省的排序順序,并且可以使用其他名稱的操作符。 如果指定`NULLS LAST`,空值會在所有非空值之后排序;如果指定 `NULLS FIRST`,空值會在所有非空值之前排序。如果兩者均未指定, 當指定`ASC`或缺省時,默認反應時是`NULLS LAST`, 并且當指定`DESC`時,默認反應時是`NULLS FIRST`(因此, 默認地認為空是大于非空的)。當指定`USING`時, 默認空排序依賴于操作符是小于還是大于操作符。 請注意排序選項僅適用于他們遵循的表達式;例如`ORDER BY x, y DESC` 不意味著與`ORDER BY x DESC, y DESC`相同。 字符類型的數據是按照應用于被排序的字段的排序規則排序的。可以在需要時通過在 `_expression_`中包含`COLLATE` 子句覆蓋,例如`ORDER BY mycolumn COLLATE "en_US"`。更多信息請參閱 [Section 4.2.10](#calibre_link-1333)和[Section 22.2](#calibre_link-667)。 ### `LIMIT` 子句 `LIMIT`子句由兩個獨立的子句組成: ``` LIMIT { _count_ | ALL } OFFSET _start_ ``` `_count_`聲明返回的最大行數, 而`_start_`聲明開始返回行之前忽略的行數。 如果兩個都指定了,那么在開始計算`_count_` 個返回行之前將先跳過`_start_`行。 如果`_count_`表達式評估為NULL, 它被當做`LIMIT ALL`,也就是,沒有限制。如果 `_start_`評估為NULL,他與 `OFFSET 0`相同對待。 SQL:2008引入了一個不同的語法來達到相同的效果,這也是PostgreSQL支持的。這是: ``` OFFSET _start_ { ROW | ROWS } FETCH { FIRST | NEXT } [ _count_ ] { ROW | ROWS } ONLY ``` 在該語法中,為`_start_`或`_count_` 提供除簡單整型常量之外的東西時,你必須寫圓括號。如果`_count_` 在`FETCH`子句中省略了,它默認為1。`ROW`和`ROWS` 以及`FIRST`和`NEXT`是不影響這些子句的效果的干擾詞。 根據該標準,若兩個都存在則`OFFSET`子句必須在`FETCH`子句之前出現; 但是PostgreSQL的要求更為寬松并且允許任意一種順序。 使用`LIMIT`的一個好習慣是使用一個`ORDER BY`子句把結果行限制成一個唯一的順序。 否則你會得到無法預料的結果子集,你可能想要第十行到第二十行,但是是以什么順序的第十行到第二十行? 除非你聲明`ORDER BY` ,否則你不知道什么順序。 查詢優化器在生成查詢規劃時會把`LIMIT`考慮進去,所以你很有可能因給出的 `LIMIT`和`OFFSET`值不同而得到不同的規劃(生成不同的行序)。 因此用不同的`LIMIT`/`OFFSET`值選擇不同的查詢結果的子集 _將不會產生一致的結果_,除非你用`ORDER BY` 強制生成一個可預計的結果順序。這可不是 bug ;這是 SQL 生來的特點, 因為除非用了`ORDER BY`約束順序,SQL 不保證查詢生成的結果有任何特定的順序。 如果沒有一個`ORDER BY`來強制選擇一個確定性子集,那么重復執行相同的 `LIMIT`查詢返回不同的表行的子集甚至都是可能的。同樣, 這不是一個漏洞;結果的確定在這種情況下沒法保證。 ### 鎖定子句 `FOR UPDATE`, `FOR NO KEY UPDATE`, `FOR SHARE` 和 `FOR KEY SHARE` 是 _鎖定子句_;他們影響 `SELECT`如何從表中鎖定行作為獲得的行。 鎖定子句的一般形式: ``` FOR _lock_strength_ [ OF _table_name_ [, ...] ] [ NOWAIT ] ``` 這里的`_lock_strength_`可以是下列之一: ``` UPDATE NO KEY UPDATE SHARE KEY SHARE ``` `FOR UPDATE`令那些被`SELECT`檢索出來的行被鎖住, 就像要更新一樣。這樣就避免它們在當前事務結束前被其它事務修改或者刪除;也就是說, 其它企圖`UPDATE`, `DELETE`, `SELECT FOR UPDATE`, `SELECT FOR NO KEY UPDATE`, `SELECT FOR SHARE` 或 `SELECT FOR KEY SHARE`這些行的事務將被阻塞,直到當前事務結束。 `FOR UPDATE`鎖模式也可以通過在一個行上`DELETE`或在特定的字段上修改值的 `UPDATE`獲得。目前,為`UPDATE`情況考慮的字段設置是那些有唯一索引并且可以用于外鍵的 (所以不考慮局部索引和表達式索引),但是這個可能會在將來改變。同樣, 如果一個來自其它事務的`UPDATE`, `DELETE`, `SELECT FOR UPDATE`已經鎖住了某個或某些選定的行,`SELECT FOR UPDATE` 將等到那些事務結束,并且將隨后鎖住并返回更新的行(或者不返回行,如果行已經被刪除)。 但是,在`REPEATABLE READ`或`SERIALIZABLE`事務內部, 如果在事務開始時要被鎖定的行已經改變了,那么將拋出一個錯誤。更多的討論參閱[Chapter 13](#calibre_link-444)。 `FOR NO KEY UPDATE`的行為類似,只是獲得的鎖比較弱:這個鎖將不鎖定 嘗試在相同的行上獲得鎖的`SELECT FOR KEY SHARE`命令。 這個鎖模式也可以通過任何不爭取`FOR UPDATE`鎖的`UPDATE`獲得。 `FOR SHARE`的行為類似,只是它在每個檢索出來的行上要求一個共享鎖, 而不是一個排它鎖。一個共享鎖阻塞其它事務在這些行上執行`UPDATE`, `DELETE`, `SELECT FOR UPDATE` 或 `SELECT FOR NO KEY UPDATE`,卻不阻止他們執行`SELECT FOR SHARE` 或 `SELECT FOR KEY SHARE`。 `FOR KEY SHARE`的行為類似于`FOR SHARE`,只是鎖比較弱: 阻塞`SELECT FOR UPDATE`但不阻塞`SELECT FOR NO KEY UPDATE`。 一個共享鍵塊阻塞其他事務執行`DELETE`或任意改變鍵值的`UPDATE`, 但是不阻塞其他`UPDATE`,也不阻止`SELECT FOR NO KEY UPDATE`, `SELECT FOR SHARE`, 或 `SELECT FOR KEY SHARE`。 為了避免操作等待其它事務提交,使用`NOWAIT`選項。如果被選擇的行不能立即被鎖住, 那么語句將會立即匯報一個錯誤,而不是等待。請注意,`NOWAIT`只適用于行級別的鎖, 要求的表級鎖`ROW SHARE`仍然以通常的方法進行(參閱[Chapter 13](#calibre_link-444))。 如果需要申請表級別的鎖同時又不等待,那么你可以使用[LOCK](#calibre_link-1151)的 `NOWAIT`選項。 如果在鎖定子句中明確指定了表名字,那么將只有這些指定的表被鎖定,其他在 `SELECT`中使用的表將不會被鎖定。 一個其后不帶表列表的鎖定子句將鎖定該聲明中所有使用的表。 如果鎖定子句應用于一個視圖或者子查詢,它同樣將鎖定所有該視圖或子查詢中使用到的表。 但是這些子句不適用于被主查詢引用的`WITH`查詢。 如果你想要行鎖定發生在`WITH`查詢中,那么在`WITH`查詢中指定鎖定子句。 多個鎖定子句可以用于為不同的表指定不同的鎖定模式。如果一個表出同時出現 (或隱含同時出現)在多個鎖定子句中,那么將看做只被最強的那個聲明了處理。 類似的,如果影響一個表的任意子句中出現了`NOWAIT`, 那么該表將按照`NOWAIT`處理。 鎖定子句不能在那些無法使用獨立的表行清晰標識返回行的環境里使用;比如,它不能和聚集一起使用。 當鎖定子句出現在`SELECT`查詢的頂層時,鎖定的行恰好是被查詢返回的行; 在連接查詢的情況下,鎖定的行是那些有助于返回連接的行。另外, 滿足查詢條件的行作為查詢快照將被鎖定,盡管如果在快照后他們被更新不再滿足查詢條件 就不再被返回。如果使用了`LIMIT`,那么一旦返回足夠的行滿足限制鎖定將停止 (但是請注意,通過`OFFSET`跳過的行將被鎖定)。相似的,如果鎖定子句用于游標查詢, 只有實際抓取到的行或通過游標跳過的行將被鎖定。 當鎖定子句出現在子`SELECT`中時,鎖定的行是那些通過子查詢返回到外查詢的行。 這些包含的行可能比單獨檢查子查詢時給出的行更少,因為外查詢的條件可能會用來優化子查詢的執行。 例如: ``` SELECT * FROM (SELECT * FROM mytable FOR UPDATE) ss WHERE col1 = 5; ``` 將只鎖定`col1 = 5`的行,即使那個條件不是子查詢中的原文。 以前的版本未能保持鎖,通過一個稍后的保存點來改善。例如,這段代碼: ``` BEGIN; SELECT * FROM mytable WHERE key = 1 FOR UPDATE; SAVEPOINT s; UPDATE mytable SET ... WHERE key = 1; ROLLBACK TO s; ``` `FOR UPDATE`鎖將會在`ROLLBACK TO`之后無法保持。這在版本9.3中已經修復了。 | **Caution** | |:--- | | 一個`SELECT`命令運行在`READ COMMITTED`事務隔離級別和使用 `ORDER BY`和一個鎖定子句返回順序混亂的行是可能的。這是因為`ORDER BY` 先生效。命令排序結果,但是可能會在其中一行或多行上獲取鎖的時候被阻塞。一旦`SELECT` 的阻塞被解除后,某些順序字段值可能被修改,導致這些行混亂了(盡管他們還是原先字段值的順序)。 可以在需要的時候通過在子查詢中放置`FOR UPDATE/SHARE`子句來避開,例如 ``` SELECT * FROM (SELECT * FROM mytable FOR UPDATE) ss ORDER BY column1; ``` 請注意這將導致鎖定`mytable`的所有行,而頂層的`FOR UPDATE` 將會實際上僅鎖住返回行。這可能會產生一個顯著的性能差異,尤其是如果`ORDER BY` 與`LIMIT`或者其他限制結合。僅當順序列的并發更新是預期的并且需要一個嚴格的排序結果時, 該技術才是建議使用的。 在`REPEATABLE READ`或`SERIALIZABLE`事務隔離級別, 這可能會導致一個序列化失敗(`SQLSTATE`為`'40001'`), 所以在這些隔離級別下接收次序混亂的行是不可能的。 | ### `TABLE` 命令 命令: ``` TABLE _name_ ``` 完全等價于: ``` SELECT * FROM _name_ ``` 它可以用作復雜查詢中的一部分的一個頂級的命令或者一個節省空間的語法變體。 ## 例子 將表`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 ... ``` 統計用`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 ``` 統計用`kind`分組的每組電影的長度`len`總和不足五小時的組: ``` 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 ``` 下面兩個例子是根據第二列(`name`)的內容對單獨的結果排序的相同的方法: ``` 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 ``` 下面這個例子演示如何獲得表`distributors`和`actors`的連接, 只將每個表中以字母 W 開頭的取出來。因為只取了不重復的行,所以關鍵字`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 ``` 這個例子顯示了如何在`FROM`子句中使用函數,包括帶有和不帶字段定義列表的。 ``` 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 ``` 這個例子顯示了如何使用一個簡單的`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 ``` 請注意`WITH`查詢只評估一次,所以我們獲得兩組相同的三個隨機值。 這個例子使用`WITH RECURSIVE` 從一個只顯示直接屬下的表中找到所有職員Mary的屬下(直接或間接),和他們的間接級別, ``` 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; ``` 請注意遞歸查詢的典型形式:一個初始條件,緊接著是`UNION`, 然后是查詢的遞歸部分。確定查詢的遞歸部分最終將不會返回元組,否則查詢將無限循環下去。 (請參閱[Section 7.8](#calibre_link-515)獲取更多示例。) 這個例子使用`LATERAL`為`manufacturers`表的每行應用一個設置返回函數 `get_product_names()`: ``` SELECT m.name AS mname, pname FROM manufacturers m, LATERAL get_product_names(m.id) pname; ``` 當前沒有任何產品的制造商將不會出現在結果中,因為這是一個內連接。 如果我們希望在結果中包括這種制造商的名字,我們可以這樣做: ``` SELECT m.name AS mname, pname FROM manufacturers m LEFT JOIN LATERAL get_product_names(m.id) pname ON true; ``` ## 兼容性 `SELECT`語句和 SQL 標準兼容。但是還有一些擴展和一些缺少的特性。 ### 省略 `FROM` 子句 PostgreSQL允許在一個查詢里省略`FROM`子句。 它的最直接用途就是計算簡單的常量表達式的結果: ``` SELECT 2+2; ?column? ---------- 4 ``` 其它有些SQL數據庫不能這么做,除非引入一個單行的偽表做為 `SELECT`的數據源。 請注意,如果沒有聲明`FROM`子句,那么查詢不能引用任何數據庫表。 比如,下面的查詢是非法的: ``` SELECT distributors.* WHERE distributors.name = 'Westward'; ``` PostgreSQL 8.1 之前的版本支持這種形式的查詢, 為查詢里引用的每個表都增加一個隱含的條目到`FROM`子句中。 現在這個不再是允許的了。 ### 省略 `AS` 關鍵字 在SQL標準中,每當新列名稱是一個有效的列名時(也就是,與任意保留關鍵字都不同), 可選的關鍵字`AS`可以在輸出列名之前省略。PostgreSQL 限制略多一些:不管是保留還是不保留,如果新列名匹配任何關鍵字,`AS`是必要的。 建議的做法是使用`AS`或者雙括號括起輸出列名稱,以阻止與將來補充的關鍵字有任何可能的沖突。 在`FROM`項中,標準和PostgreSQL都允許`AS` 在一個無限制關鍵字別名之前省略。但是這對輸出列名是不切實際的,因為語法的歧義。 ### `ONLY`和繼承 SQL標準需要在寫`ONLY`時括號括起表名,例如 `SELECT * FROM ONLY (tab1), ONLY (tab2) WHERE ...`。 PostgreSQL認為括號是可選的。 PostgreSQL允許寫一個尾隨的`*`以明確指定包括子表的非 `ONLY`行為。標準不允許這樣。 (該點同樣適用于所有支持`ONLY`選項的SQL命令。) ### `FROM`中的函數調用 PostgreSQL允許把函數調用直接寫作`FROM`列表的一個成員。 在SQL標準中應該有必要在子`SELECT`中包含這樣一個函數;也就是, 該語法`FROM` `_func_`(...) `_alias_`等價于 `FROM LATERAL (SELECT` `_func_`(...)) `_alias_`。 請注意`LATERAL`被認為是隱含的;這是因為標準要求`LATERAL`語義為 一個在`FROM`中的`UNNEST()`條目。PostgreSQL 對待`UNNEST()`和其他設置返回函數相同。 ### `GROUP BY` 和 `ORDER BY`里可用的命名空間 在 SQL-92 標準里,`ORDER BY`子句只能使用輸出字段名或者編號, 而`GROUP BY`子句只能用基于輸入字段名的表達式。PostgreSQL 對這兩個子句都進行了擴展,允許另外一種選擇(但是如果存在歧義,則使用標準的解釋)。 PostgreSQL還允許兩個子句聲明任意的表達式。 請注意在表達式中出現的名字總是被當作輸入字段名,而不是輸出字段名。 SQL:1999 以及之后的一個略微不同的定義并不能和 SQL-92 完全向前兼容。不過, 在大多數情況下,PostgreSQL將把一個`ORDER BY` 或`GROUP BY`表達式解析成為 SQL:1999 制定的那樣。 ### 函數依賴 PostgreSQL只在表的主鍵包含在`GROUP BY` 列表中時識別函數依賴(允許在`GROUP BY`中省略字段)。 SQL標準指定應該被識別的附加條件。 ### `WINDOW` 子句限制 SQL標準為窗口`_frame_clause_`提供了附加選項。 PostgreSQL目前僅支持上面列出的選項。 ### `LIMIT` 和 `OFFSET` 子句`LIMIT`和`OFFSET`是PostgreSQL 特定的語法,也是MySQL使用的。SQL:2008標準引入了 `OFFSET ... FETCH {FIRST|NEXT} ...`獲取相同的功能, 如上面的[_LIMIT_ 子句](#calibre_link-1059)子句所示。 該語法也被IBM DB2使用。(為Oracle 所寫的應用程序通常使用一個涉及自動生成的`rownum`列的工作區, 來實現這些子句的效果,這在PostgreSQL中是不可用的。) ### `FOR NO KEY UPDATE`, `FOR UPDATE`, `FOR SHARE`, `FOR KEY SHARE` 盡管`FOR UPDATE`出現在了SQL標準中,但是標準只允許它作為`DECLARE CURSOR` 的一個選項。PostgreSQL允許它出現在任意`SELECT` 查詢和子`SELECT`查詢中,但是這是一個擴展。`FOR NO KEY UPDATE`, `FOR SHARE`, `FOR KEY SHARE`變體和`NOWAIT`選項, 沒有出現在標準中。 ### `WITH`中的數據修改語句 PostgreSQL允許`INSERT`, `UPDATE`, `DELETE` 用作`WITH`查詢。這在SQL標準中是沒有的。 ### 非標準的子句 子句`DISTINCT ON`在SQL標準中未定義。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看