<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>

                企業??AI智能體構建引擎,智能編排和調試,一鍵部署,支持知識庫和私有化部署方案 廣告
                # 4.2\. 值表達式 值表達式用在各種語法環境中,比如在`SELECT`命令的目標列表中, 在`INSERT`或`UPDATE`中用作新的列值, 或者在許多命令的搜索條件中使用。我們有時候把值表達式的結果叫做_標量_, 以便與一個表表達式的結果相區別(是一個表)。因此值表達式也叫做 _標量表達式_(或簡稱_表達式_)。 表達式語法允許對來自基本部分的數值進行算術、邏輯、集合、和其它運算。 值表達式是下列內容之一: * 一個常量或者字面值 * 一個字段引用 * 一個位置參數引用(在函數聲明體中或預編寫的語句中) * 一個下標表達式 * 一個字段選擇表達式 * 一個操作符調用 * 一個函數調用 * 一個聚集表達式 * 一個窗口函數調用 * 一個類型轉換 * 一個排序規則表達式 * 一個標量子查詢 * 一個數組構造器 * 一個行構造器 * 一個在圓括弧里面的值表達式(可用于子表達式分組和覆蓋優先級)。 除了這個列表以外,還有許多構造可以歸類為表達式,但是不遵循任何通用的語法規則。 它們通常有函數或操作符的語義,并且在[Chapter 9](#calibre_link-455)里合適的位置描述。 一個例子是`IS NULL`子句。 我們已經在[Section 4.1.2](#calibre_link-698)里討論過常量了。下面的節討論剩下的選項。 ## 4.2.1\. 字段引用 一個字段可以用下面的形式引用: ``` _correlation_._columnname_ ``` `_correlation_`是一個表的名字(可能有模式修飾), 或者是用`FROM`子句這樣的方法定義的表的別名。 如果在當前查詢所使用的所有表中,該字段名字是唯一的, 那么這個相關名字(correlation)和分隔用的點就可以省略(參見[Chapter 7](#calibre_link-485))。 ## 4.2.2\. 位置參數 位置參數引用用于標識從外部給 SQL 語句的參數。參數用于 SQL 函數定義語句和預編寫的查詢。有些客戶端庫還支持在 SQL 命令字符串外邊聲明數據值, 這種情況下參數用于引用 SQL 字符串行外的數據。一個參數的形式如下: ``` $_number_ ``` 比如下面這個`dept`函數的定義: ``` CREATE FUNCTION dept(text) RETURNS dept AS $$ SELECT * FROM dept WHERE name = $1 $$ LANGUAGE SQL; ``` 在函數被調用的時候這里的`$1`將引用第一個參數。 ## 4.2.3\. 下標 如果一個表達式生成一個數組類型的數值, 那么我們可以通過下面這樣的表達式來提取數組中的元素 ``` _expression_[_subscript_] ``` 或者如果是多個相鄰的元素("數組片斷")可以用下面的方法抽取 ``` _expression_[_lower_subscript_:_upper_subscript_] ``` (這里的方括號`[ ]`按照字面文本的方式出現。) 每個`_subscript_`自己都是一個表達式,它必須生成一個整數值。 通常,數組`_expression_`必須用圓括弧包圍, 但如果只是一個字段引用或者一個位置參數,那么圓括弧可以省略。同樣, 如果源數組是多維的,那么多個下標可以連接在一起。比如: ``` mytable.arraycolumn[4] mytable.two_d_column[17][34] $1[10:42] (arrayfunction(a,b))[42] ``` 最后一個例子里的圓括弧是必須的。參閱[Section 8.15](#calibre_link-1759)獲取有關數組的更多信息。 ## 4.2.4\. 字段選擇 如果一個表達式生成一個復合類型(行類型),那么用下面的方法可以抽取一個指定的字段 ``` _expression_._fieldname_ ``` 通常,行`_expression_`必須用圓括弧包圍, 但是如果要選取的表達式只是一個表引用或者位置參數,可以省略圓括弧。比如: ``` mytable.mycolumn $1.somecolumn (rowfunction(a,b)).col3 ``` 因此,一個全稱的字段引用實際上只是一個字段選擇語法的特例。 一個重要的特殊情形是提取的表列是一個復合型的字段: ``` (compositecol).somefield (mytable.compositecol).somefield ``` 在這里,括號是必須的,用來指出`compositecol`是列名而不是表名, `mytable`是表名而不是模式名。 在一個選擇列表中(查看[Section 7.3](#calibre_link-483)), 你可以通過使用`.*`來要求所有的組合值字段。 ``` (compositecol).* ``` ## 4.2.5\. 操作符調用 操作符調用有三種語法: | `_expression_` `_operator_` `_expression_` (雙目中綴操作符) | |:--- | | `_operator_` `_expression_` (單目前綴操作符) | | `_expression_` `_operator_` (單目后綴操作符) | 這里的`_operator_`記號遵循[Section 4.1.3](#calibre_link-1924)的語法規則, 或者是記號`AND`,`OR`,`NOT`之一。 或者是一個被修飾的操作符名: ``` OPERATOR(_schema_._operatorname_) ``` 具體存在哪個操作符以及它們是單目還是雙目取決于系統或用戶定義了什么操作符。 [Chapter 9](#calibre_link-455)描述了內置的操作符。 ## 4.2.6\. 函數調用 函數調用的語法是合法函數名(可能有模式名修飾),后面跟著包含參數列表的圓括弧: ``` _function_name_ ([`_expression_` [, `_expression_` ... ]] ) ``` 比如,下面的代碼計算 2 的平方根: ``` sqrt(2) ``` 內置函數的列表在[Chapter 9](#calibre_link-455)里。其它函數可由用戶添加。 可選的可附加名字的參數,詳細請參閱[Section 4.3](#calibre_link-733)。 > **Note:** 一個接受一個復合類型參數的函數,可以使用字段選擇語法調用,相反的, 字段選擇可以用函數的風格寫出來。也就是說,符號`col(table)` 和 `table.col`是可以互換的。這個行為不是SQL標準,但是由 PostgreSQL提供,因為它允許函數使用仿真"計算域"。 獲取更多信息,請參閱[Section 35.4.3](#calibre_link-912)。 ## 4.2.7\. 聚集表達式 一個_聚集表達式_代表一個聚集函數對查詢選出的行的處理。 一個聚集函數把多個輸入縮減為一個輸出值,比如給輸入求和或求平均。 一個聚集表達式的語法是下列之一: ``` _aggregate_name_ (_expression_ [ , ... ] [ _order_by_clause_ ] ) _aggregate_name_ (ALL _expression_ [ , ... ] [ _order_by_clause_ ] ) _aggregate_name_ (DISTINCT _expression_ [ , ... ] [ _order_by_clause_ ] ) _aggregate_name_ ( * ) ``` 這里的`_aggregate_name_`是前面定義的聚集(可能是帶有模式的全稱), 而`_expression_`是一個本身不包含聚集表達式或一個窗口函數調用的任意值表達式。 `_order_by_clause_`是`ORDER BY` 子句的一個選項,下面會有描述。 第一種形式的聚集表達式為每個輸入行調用聚集。 第二種形式與第一種等價(因為`ALL`是缺省值)。 第三種形式為每個表達式中不同的值調用聚集(或者為多個表達式不同的值的集合)。 最后一種形式為每個輸入行調用一次聚集,因為沒有聲明特定的輸入值, 通常它只用于`count(*)`聚集函數。 大多數的聚集函數忽略了NULL輸入,因此在一個或多個表達式中產生NULL的行會被丟棄。 對所有的內置聚集函數而言,這樣做是可以的,除非另行說明。 比如,`count(*)`生成輸入行的總數;`count(f1)`生成 `f1`不為 NULL 的輸入行數,因為`count`忽略NULL; `count(distinct f1)`生成`f1`唯一且非 NULL 的行數。 一般情況下,輸入行會以非特定順序放入到聚集函數中。在許多情況下,這樣做是沒有影響的; 如,無論以什么順序輸入,`min`輸出相同的結果。然而, 一些聚集函數(如`array_agg` 和 `string_agg`)并非如此。 當使用這種聚集函數時,可以用`_order_by_clause_`選項指定輸入的順序。 除了它的表達式僅僅只是表達式,并且不能輸出列名或列數之外,`_order_by_clause_` 與`ORDER BY`查詢子句有相同的語法結構,在[Section 7.5](#calibre_link-1466)中有描述,如: ``` SELECT array_agg(a ORDER BY b DESC) FROM table; ``` 在處理多參數聚集函數時需要注意,`ORDER BY`子句要在所有的聚集函數參數之后,如這樣寫: ``` SELECT string_agg(a, ',' ORDER BY a) FROM table; ``` 而不是: ``` SELECT string_agg(a ORDER BY a, ',') FROM table; -- incorrect ``` 后者在語法上是有效的,但它表示的是, 有兩個`ORDER BY`關鍵字的單參數的聚集函數的調用(第二個是無用的, 因為它是一個常量)。 如果`_order_by_clause_`中聲明了`DISTINCT`, 那么所有的`ORDER BY`表達式必須匹配規則的聚集參數,也就是說, 不能對沒有包含在`DISTINCT`列表中的表達式進行排序。 > **Note:** 同時在一個聚集函數中聲明`DISTINCT`和`ORDER BY`是PostgreSQL的一個擴展。 預定義的聚集函數在[Section 9.20](#calibre_link-1641)里描述。其它聚集函數可以由用戶增加。 一個聚集表達式只能在`SELECT`命令的結果列表或者`HAVING`子句里出現。 禁止在其它子句里出現(比如`WHERE`子句),因為這些子句邏輯上在生成聚集結果之前計算。 如果一個聚集表達式出現在一個子查詢里(參閱[Section 4.2.11](#calibre_link-1953) 和[Section 9.22](#calibre_link-1795)),聚集通常是在子查詢中進行計算。 但是如果聚集的參數只包含外層查詢的變量則例外:這個聚集會屬于離他最近的外層查詢, 并且在該查詢上進行計算。該聚集表達式整體上屬于它出現的子查詢對外層查詢的引用, 其作用相當于子查詢每一次計算中的一個常量。前述限制(聚集表達式只能出現在結果列或者 `HAVING`子句中)只適用于聚集所屬的查詢層。 ## 4.2.8\. 窗口調用函數 通過查詢篩選出的行的某些部分,_窗口調用函數_實現了類似于聚集函數的功能。 不同的是,窗口調用函數不需要將查詢結果打包成一行輸出—在查詢輸出中,每一行都是分開的。 然而,窗口調用函數可以掃描所有的行,根據窗口調用函數的分組規范(`PARTITION BY`列), 這些行可能會是當前行所在組的一部分。一個窗口調用函數的語法是下列之一: ``` _function_name_ ([`_expression_` [, `_expression_` ... ]]) OVER ( _window_definition_ ) _function_name_ ([`_expression_` [, `_expression_` ... ]]) OVER _window_name_ _function_name_ ( * ) OVER ( _window_definition_ ) _function_name_ ( * ) OVER _window_name_ ``` 這里的`_window_definition_`具有如下語法: ``` [ _existing_window_name_ ] [ PARTITION BY _expression_ [, ...] ] [ ORDER BY _expression_ [ ASC | DESC | USING _operator_ ] [ NULLS { FIRST | LAST } ] [, ...] ] [ _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 ``` 在這里,`_expression_` 表示的是任何自己不含窗口調用函數的值表達式。 `_window_name_`引用的是查詢語句中`WINDOW` 子句定義的命名窗口規范。命名窗口規范通常只是用`OVER` `_window_name_` 來引用,但它也可以在括號里寫一個窗口名,并且可以有選擇的使用排序和/或框架(frame)子句 (如果應用這些子句的話,那么被引用的窗口必須不能有這些子句)。 后者語法遵循相同的規則(修改`WINDOW`子句中已有的窗口名)。 參閱[SELECT](#calibre_link-104)查看更多資料。 `PARTITION BY`選項將查詢的行分為一組進入_partitions_, 這些行在窗口函數中單獨處理。`PARTITION BY`和查詢級別`GROUP BY` 子句做相似的工作,除了它的表達式只能作為表達式不能作為輸出列的名字或數。 沒有`PARTITION BY`,所有由查詢產生的行被視為一個單獨的分區。`ORDER BY` 選項決定分區中的行被窗口函數處理的順序。它和查詢級別`ORDER BY`子句做相似的工作, 但是同樣的它不能作為輸出列的名字或數。沒有`ORDER BY`,行以一個不被預知的順序處理。 對這些窗口函數(在這個框架而不是整個分區上的), `_frame_clause_`指定構成_window frame_的行, 他們是當前分區的一個子集。框架可以用`RANGE` 或 `ROWS`模式聲明;不管哪種情況, 它的變化范圍是從`_frame_start_`到`_frame_end_`。如果省略了`_frame_end_` 默認為`CURRENT ROW`。 一個`_frame_start_`的`UNBOUNDED PRECEDING`意味著框架從分區中的第一行開始, 相似的,一個`_frame_end_`的`UNBOUNDED FOLLOWING`意味著框架從分區中的最后一行結束。 在`RANGE`模式中,`_frame_start_`的`CURRENT ROW` 意味著框架從當前行的第一個_peer_行開始(`ORDER BY` 認為等于當前行的行),而`_frame_end_`的`CURRENT ROW` 意味著框架從最后一個同等的行結束。在`ROWS`模式中, `CURRENT ROW` 簡單的意味著當前行。 `_value_` `PRECEDING`和`_value_` `FOLLOWING` 當前只允許`ROWS`模式。這也就意味著,框架從當前行之前或之后指定的行數啟動或結束。 `_value_`必須是整型表達式,而不能包含變量,聚集函數,或者窗口函數。 該值不能為空或負,但可以是零,表示只選擇當前行本身。 默認的框架選項是`RANGE UNBOUNDED PRECEDING`,該選項與 `RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW`相同。有`ORDER BY`, 它設置框架從分區的開始一直到與當前行相同的最后一行。沒有`ORDER BY`, 那么就是當前分區的所有行都包含在框架中,因為所有行都會成為當前行的相同行。 限制條件是`_frame_start_`不能為`UNBOUNDED FOLLOWING`, `_frame_end_`不能為`UNBOUNDED PRECEDING`,并且`_frame_end_` 選項不能在上面的列表中出現的比`_frame_start_`選項早—例如 `RANGE BETWEEN CURRENT ROW AND` `_value_` PRECEDING是不被允許的。 內置窗口函數在[Table 9-48](#calibre_link-2162)中有描述。其他窗口函數, 用戶可以自己添加。同樣,任意內置或用戶自定義聚集函數可以同窗口函數一樣使用。 使用`*`的語法可以用來調用無參數的聚集函數為窗口函數,如 `count(*) OVER (PARTITION BY x ORDER BY y)`。星號(`*`) 通常不用于非聚集的窗口函數。與通常的聚集函數不同,聚集窗口函數不允許在函數參數列中使用 `DISTINCT`或`ORDER BY`。 窗口調用函數只能在`SELECT`列,或者查詢的`ORDER BY`子句中使用。 更多關于窗口函數的信息可以參考: [Section 3.5](#calibre_link-1330), [Section 9.21](#calibre_link-1804), [Section 7.2.4](#calibre_link-1332). ## 4.2.9\. 類型轉換 一個類型轉換聲明一個從一種數據類型到另外一種數據類型的轉換。 PostgreSQL接受兩種等效的類型轉換語法: ``` CAST ( _expression_ AS _type_ ) _expression_::_type_ ``` `CAST`語法遵循 SQL 標準;`::`語法是PostgreSQL歷史用法。 如果對一個已知類型的值表達式應用轉換,它代表一個運行時類型轉換。 只有在已經定義了合適的類型轉換操作的情況下,該轉換才能成功。 請注意這一點和用于常量的轉換略有區別(如[Section 4.1.2.7](#calibre_link-788)所示)。 一個應用于字符串文本的轉換表示給該字符串文本的常數值賦予一個初始類型, 因此它對于任何類型都會成功(如果字符串文本的內容符合該數據類型的輸入語法)。 如果一個值表達式的值對某類型而言不存在混淆的情況,那么我們可以省略明確的類型轉換(比如, 在給一個表字段賦值的時候),而由系統自動執行類型轉換。不過, 自動轉換只適用于那些系統表中標記著"OK to apply implicitly"的轉換函數。 其它轉換函數必須用明確的轉換語法調用。這些限制是為了避免一些怪異的轉換被自動的應用。 我們也可以用函數風格的語法聲明一個類型轉換: ``` _typename_ ( _expression_ ) ``` 不過,這個方法只能用于那些類型名同時也是有效函數名的類型。比如, `double precision`就不能這么用,但是等效的`float8` 可以。同樣,`interval`,`time`和`timestamp` 如果加了雙引號也只能這么用,因為存在語法沖突。因此,函數風格的類型轉換會導致不一致, 所以應該避免這么使用。 > **Note:** 函數風格語法實際上就是一個函數調用。如果使用兩種標準轉換語法做運行時轉換, 那么它將在內部調用一個已注冊的函數執行轉換。通常,這種轉換函數和它們的輸出類型同名, 因此"函數風格語法"只不過是直接調用底層轉換函數。 但是可以移植的程序不能依賴這一點。詳情請參閱[CREATE CAST](#calibre_link-556)。 ## 4.2.10\. 排序規則表達式 `COLLATE`子句重寫了表達式的排序規則。它附加到要應用的表達式上: ``` _expr_ COLLATE _collation_ ``` 這里的`_collation_`是一個可能的模式限定標識符。 `COLLATE`子句綁定得比操作符更緊密;需要時可以用括號。 如果沒有明確聲明排序規則,數據庫系統要么從表達式中的列獲取一個排序規則, 要么如果表達式中沒有包含列,使用數據庫的默認排序規則。 `COLLATE`子句的兩個常見的使用是重寫`ORDER BY`子句里的排序次序, 例如: ``` SELECT a, b, c FROM tbl WHERE ... ORDER BY a COLLATE "C"; ``` 和重寫執行結果區域敏感的函數或運算符調用的排序規則,例如: ``` SELECT * FROM tbl WHERE a > 'foo' COLLATE "C"; ``` 請注意,在后面一種情況下,`COLLATE`子句附加到我們希望作用的運算符的輸入參數。 `COLLATE`子句附加到運算符或者調用函數的哪個參數不重要, 因為運算符或者函數的排序規則是考慮所有參數得到的,并且一個明確的`COLLATE` 子句將重寫所有其他參數的排序規則。(附加不匹配的`COLLATE`子句到多個參數, 是一個錯誤。更多詳細信息請參閱[Section 22.2](#calibre_link-667)。)因此, 下面的例子給出前一個例子相同的結果: ``` SELECT * FROM tbl WHERE a COLLATE "C" > 'foo'; ``` 但是這樣做是錯誤的: ``` SELECT * FROM tbl WHERE (a > 'foo') COLLATE "C"; ``` 因為它嘗試應用一個排序規則到`&gt;`運算符的結果,而這個結果是非排序規則類型`boolean`。 ## 4.2.11\. 標量子查詢 一個標量子查詢是一個放在圓括弧里只返回一行一列的普通`SELECT` 查詢(參閱[Chapter 7](#calibre_link-485)獲取有關書寫查詢的信息)。該`SELECT` 將被執行,而其返回值將在周圍的值表達式中使用。 把一個返回超過一行或者超過一列的查詢用做標量查詢是錯誤的。 (不過,在一個特定的表達式中,子查詢不返回行則不算錯誤;標量結果被認為是 NULL)。 子查詢可以引用外圍查詢的變量,這些變量在每次子查詢中當做常量使用。 參見[Section 9.22](#calibre_link-1795)以獲取其它包含子查詢的表達式。 比如,下面的查詢找出每個州中的最大人口數量的城市: ``` SELECT name, (SELECT max(pop) FROM cities WHERE cities.state = states.name) FROM states; ``` ## 4.2.12\. 數組構造器 一個數組構造器是一個表達式,它從自身成員元素上構造一個數組值。 一個簡單的數組構造器由關鍵字`ARRAY`、一個左方括弧 `[`、一個或多個表示數組元素值的表達式(用逗號分隔)、一個右方括弧`]` 組成。比如: ``` SELECT ARRAY[1,2,3+4]; array --------- {1,2,7} (1 row) ``` 默認的,數組元素類型是成員表達式的公共類型,使用和`UNION`或 `CASE`構造一樣的規則決定(參閱[Section 10.5](#calibre_link-454))。 你可以通過明確地轉換數組構造器為想要的類型來重寫這個規則,例如: ``` SELECT ARRAY[1,2,22.7]::integer[]; array ---------- {1,2,23} (1 row) ``` 這和單獨構造每個表達式為數組元素類型有相同的效果。關于構造的更多信息,請參閱[Section 4.2.9](#calibre_link-1793)。 多維數組值可以通過嵌套數組構造器的方法來制作。內層構造器中的`ARRAY` 關鍵字可以省略。比如,下面的兩句生成同樣的結果: ``` SELECT ARRAY[ARRAY[1,2], ARRAY[3,4]]; array --------------- {{1,2},{3,4}} (1 row) SELECT ARRAY[[1,2],[3,4]]; array --------------- {{1,2},{3,4}} (1 row) ``` 因為多維數組必須是方形,所以同層的內層構造器必須生成同維的子數組。 任何應用于外層`ARRAY`構造器的類型轉換自動的應用到所有的內層構造器。 多維數組構造器元素可以是任何生成合適數組的東西,而不僅僅是一個子`ARRAY`構造。比如: ``` CREATE TABLE arr(f1 int[], f2 int[]); INSERT INTO arr VALUES (ARRAY[[1,2],[3,4]], ARRAY[[5,6],[7,8]]); SELECT ARRAY[f1, f2, '{{9,10},{11,12}}'::int[]] FROM arr; array ------------------------------------------------ {{{1,2},{3,4}},{{5,6},{7,8}},{{9,10},{11,12}}} (1 row) ``` 因為數組必須得有類型,因此在構造一個空數組時,必須明確的將其構造成需要的類型,如: ``` SELECT ARRAY[]::integer[]; array ------- {} (1 row) ``` 我們也可以從一個子查詢的結果中構造一個數組。此時, 數組構造器是關鍵字`ARRAY`后跟著一個用圓括弧(不是方括弧)包圍的子查詢。比如: ``` SELECT ARRAY(SELECT oid FROM pg_proc WHERE proname LIKE 'bytea%'); array ----------------------------------------------------------------------- {2011,1954,1948,1952,1951,1244,1950,2005,1949,1953,2006,31,2412,2413} (1 row) ``` 子查詢必須只返回一個單獨的字段。生成的一維數組將為子查詢里每行結果生成一個元素, 元素類型匹配子查詢的輸出字段。 用`ARRAY`建立的數組下標總是從1開始。 有關數組的更多信息,參閱[Section 8.15](#calibre_link-1759)。 ## 4.2.13\. 行構造器 行構造器是一個從提供給它的成員字段數值中構造行值(也叫復合類型值)的表達式。 一個行構造器由關鍵字`ROW`、一個左圓括弧、零個或多個作為行字段值的表達式(用逗號分隔)、 一個右圓括弧組成。比如: ``` SELECT ROW(1,2.5,'this is a test'); ``` 如果在列表里有多個表達式,那么關鍵字`ROW`是可選的。 行構造器可以包含`_rowvalue_``.*`語法, 它將被擴展為行值元素的列表,就像將`.*`語法用于一個`SELECT` 列表頂層一樣。例如,如果表`t`有`f1`和`f2`兩個字段, 那么下面兩句是等價的: ``` SELECT ROW(t.*, 42) FROM t; SELECT ROW(t.f1, t.f2, 42) FROM t; ``` > **Note:** 在PostgreSQL 8.2之前,`.*`語法是不會被擴展的, 所以`ROW(t.*, 42)` 將創建一個兩字段的行,其第一個字段是另一行的值。 新的行為通常更有用。如果你需要舊式的嵌套行值的做法,請將內部的行值寫成不包含`.*`, 比如`ROW(t, 42)`。 缺省時,`ROW`表達式創建的值是一個匿名的記錄類型。如果必要, 你可以把它轉換成一個命名的復合類型(既可以是一個表的行類型, 也可以是一個用`CREATE TYPE AS`創建的復合類型)。 可能會需要一個明確的轉換以避免歧義。比如: ``` CREATE TABLE mytable(f1 int, f2 float, f3 text); CREATE FUNCTION getf1(mytable) RETURNS int AS 'SELECT $1.f1' LANGUAGE SQL; -- 因為只有一個getf1()存在,所以不需要類型轉換 SELECT getf1(ROW(1,2.5,'this is a test')); getf1 ------- 1 (1 row) CREATE TYPE myrowtype AS (f1 int, f2 text, f3 numeric); CREATE FUNCTION getf1(myrowtype) RETURNS int AS 'SELECT $1.f1' LANGUAGE SQL; -- 現在我們需要類型轉換以表明調用哪個函數: SELECT getf1(ROW(1,2.5,'this is a test')); ERROR: function getf1(record) is not unique SELECT getf1(ROW(1,2.5,'this is a test')::mytable); getf1 ------- 1 (1 row) SELECT getf1(CAST(ROW(11,'this is a test',2.5) AS myrowtype)); getf1 ------- 11 (1 row) ``` 行構造器可以用于制作存儲在復合類型字段中的復合類型值, 或者是傳遞給一個接受復合類型參數的函數。另外, 我們也可以用它比較兩個行值或者用`IS NULL` 或`IS NOT NULL`測試一個行值,比如: ``` SELECT ROW(1,2.5,'this is a test') = ROW(1, 3, 'not the same'); SELECT ROW(table.*) IS NULL FROM table; -- detect all-null rows ``` 更多的細節,請參閱[Section 9.23](#calibre_link-1529)。 行構造器還可以用于連接子查詢,這些在[Section 9.22](#calibre_link-1795)里面有詳細討論。 ## 4.2.14\. 表達式計算規則 子表達式的計算順序是未定義的。特別要指出的是, 一個操作符或者函數的輸入并不一定是按照從左向右的順序或者以某種特定的順序進行計算的。 另外,如果一個表達式的結果可以通過只判斷它的一部分就可以得到, 那么其它子表達式就可以完全不計算了。比如,如果我們這么寫: ``` SELECT true OR somefunc(); ``` 那么`somefunc()`就(可能)根本不會被調用。 即使像下面這樣寫也是一樣: ``` SELECT somefunc() OR true; ``` 請注意這和某些編程語言里從左向右"短路"布爾操作符是不一樣的。 因此,拿有副作用的函數作為復雜表達式的一部分是不明智的。 在`WHERE`和`HAVING`子句里依賴副作用或者是計算順序是特別危險的, 因為這些子句都是作為生成一個執行規劃的一部分進行了大量的再處理。 在這些子句里的布爾表達式(`AND`/`OR`/`NOT` 的組合)可以用布爾代數運算律允許的任何方式進行識別。 如果需要強制計算順序,那么可以使用`CASE`構造(參閱[Section 9.17](#calibre_link-1839))。 比如,下面是一種企圖避免在`WHERE`子句里被零除的不可靠方法: ``` SELECT ... WHERE x > 0 AND y/x > 1.5; ``` 但是下面這個是安全的: ``` SELECT ... WHERE CASE WHEN x > 0 THEN y/x > 1.5 ELSE false END; ``` 這種風格的`CASE`構造會阻止優化,因此應該只在必要的時候才使用。 在這個特殊的例子里,毫無疑問寫成 `y &gt; 1.5*x`更好。
                  <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>

                              哎呀哎呀视频在线观看