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

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                # 35.4\. 查詢語言(SQL)函數 SQL函數執行SQL語句的任意列表,返回列表中最后一個查詢結果。 在簡單情況下(非-集合),將返回最后查詢結果的第一行。 (記住多行結果的"第一行"是不明確的 除非你使用`ORDER BY`。) 如果最后查詢沒有返回任何行,則返回空值。 另外,一個SQL函數可以聲明為返回一個集合(即多行)。 方法是把該函數的返回類型聲明為`SETOF` `_sometype_`。 或者等價聲明它為`RETURNS TABLE(``_columns_`)。 這種情況下,最后一條查詢結果的所有行都會被返回。更多細節在下面講解。 SQL函數的函數體應該是一個用分號分隔的SQL語句列表。 最后一個語句后面的分號是可選的。除非函數聲明為返回`void`, 否則最后一條語句必須是`SELECT`或者`INSERT`, `UPDATE`或者有`RETURNING`子句的 `DELETE`。 任何SQL命令集合都可以打包在一起,定義成新的函數。 除了`SELECT`查詢之外,命令可以包含修改數據的查詢 (`INSERT`, `UPDATE`和`DELETE`)以及其它 SQL命令。(你不能使用事務控制命令,比如`COMMIT`, `SAVEPOINT`和 一些實用命令,比如`VACUUM`,SQL)。 不過,最后一條命令必須是一個`SELECT`語句, 或者有`RETURNING`子句返回函數的返回類型。另外, 如果你只想定義一連串動作而無需返回任何數值,可以定義返回`void`。 比如,下面這個函數從`emp`表刪除負數的薪水: ``` CREATE FUNCTION clean_emp() RETURNS void AS ' DELETE FROM emp WHERE salary < 0; ' LANGUAGE SQL; SELECT clean_emp(); clean_emp ----------- (1 row) ``` `CREATE FUNCTION`命令的語法要求函數體寫成一個字符串文本。 一般來說,字符串常量使用美元符界定更方便些(參閱[Section 4.1.2.4](#calibre_link-736))。 如果你決定使用通常的字符串常量語法,你必須加單引號標記(`'`)和和反斜杠(`\`), 在函數體中(假定使用逃逸字符串語法)(參見[Section 4.1.2.1](#calibre_link-969))。 ## 35.4.1\. Arguments for SQL Functions 在函數體中使用名稱或數字引用SQL函數的參數。這兩種方法的例子在下面。 使用一個名字,聲明有名稱的函數參數,然后在函數體中寫上這個名字。如果參數名稱 在當前SQL命令的同一函數中與任何列的名稱相同,將優先考慮列名稱。為了重寫, 限定參數名與函數名本身,也就是說`_function_name_`.`_argument_name_`。 (如果有一個合格的列名稱沖突,再次列名稱獲勝。你可以通過選擇一個SQL命令表不同的別名來避免歧義。) 在舊的數值方法中,使用語法`$``_n_`: `$1`引用第一個輸入參數, `$2`到第二個,等等。是否聲明帶有名字的特定參數將要工作。 如果一個參數是復合類型,然后圓點標記法,比如,`argname.fieldname`或者 `$1.fieldname`可以用于訪問參數屬性。再次,你可能需要限定函數名的參數名 來形成模糊參數名形式。 SQL函數參數只能作為數據值使用,而不能作為標示符。因此比如這是合理的: ``` INSERT INTO mytable VALUES ($1); ``` but this will not work: ``` INSERT INTO $1 VALUES (42); ``` > **Note:** 使用名稱引用SQL函數參數的功能被添加到PostgreSQL 9.2中。 在舊的服務器中使用的函數必須使用`$``_n_`標記法。 ## 35.4.2\. 基本類型上的SQL函數 最簡單的SQL函數可能沒有參數并且返回一個基本類型, 比如一個返回`integer`的函數: ``` CREATE FUNCTION one() RETURNS integer AS $$ SELECT 1 AS result; $$ LANGUAGE SQL; --另外一種字符串文本的語法: CREATE FUNCTION one() RETURNS integer AS ' SELECT 1 AS result; ' LANGUAGE SQL; SELECT one(); one ----- 1 ``` 請注意我們在函數體里面定義了一個字段別名(`result`)用于函數結果, 但是這個字段別名在函數外面是不可見的。因此, 結果是以`one`而不是`result`為標簽的。 定義一個接受基本類型做參數的SQL函數幾乎一樣簡單。 ``` CREATE FUNCTION add_em(x integer, y integer) RETURNS integer AS $$ SELECT x + y; $$ LANGUAGE SQL; SELECT add_em(1, 2) AS answer; answer -------- 3 ``` 或者,我們可以摒棄參數名,并且使用數字: ``` CREATE FUNCTION add_em(integer, integer) RETURNS integer AS $$ SELECT $1 + $2; $$ LANGUAGE SQL; SELECT add_em(1, 2) AS answer; answer -------- 3 ``` 下面是一個更有用的函數,我們可以用它對一個銀行帳號做扣款動作: ``` CREATE FUNCTION tf1 (accountno integer, debit numeric) RETURNS integer AS $$ UPDATE bank SET balance = balance - debit WHERE accountno = tf1.accountno; SELECT 1; $$ LANGUAGE SQL; ``` 可以像下面這樣用這個函數給帳戶17扣款$100.00: ``` SELECT tf1(17, 100.0); ``` 在這個例子中,我們選擇名稱`accountno`作為第一個參數,但是這和`bank` 表中的列名是一樣的。在`UPDATE`命令中,`accountno`引用列`bank.accountno`, 因此,必須使用`tf1.accountno`來引用參數。當然我們可以通過使用 參數的不同名稱來避免這種情況。 實際上我們可能希望函數有一個比常量1更有用一些的結果。所以實用的定義可能是 ``` CREATE FUNCTION tf1 (accountno integer, debit numeric) RETURNS integer AS $$ UPDATE bank SET balance = balance - debit WHERE accountno = tf1.accountno; SELECT balance FROM bank WHERE accountno = tf1.accountno; $$ LANGUAGE SQL; ``` 它修改余額并返回新的余額。可以在命令中使用`RETURNING`做同樣的事情: ``` CREATE FUNCTION tf1 (accountno integer, debit numeric) RETURNS integer AS $$ UPDATE bank SET balance = balance - debit WHERE accountno = tf1.accountno RETURNING balance; $$ LANGUAGE SQL; ``` ## 35.4.3\. 復合類型上的SQL函數 當書寫使用用復合類型做參數的函數時,不僅要聲明需要哪個參數, 而且要聲明參數的字段(數據域)。比如,假設`emp`是一個包含雇員信息的表, 并且因此也是該表每行的復合類型的名字。一個計算某人薪水翻番之后數值的`double_salary`函數: ``` CREATE TABLE emp ( name text, salary numeric, age integer, cubicle point ); INSERT INTO emp VALUES ('Bill', 4200, 45, '(2,1)'); CREATE FUNCTION double_salary(emp) RETURNS numeric AS $$ SELECT $1.salary * 2 AS salary; $$ LANGUAGE SQL; SELECT name, double_salary(emp.*) AS dream FROM emp WHERE emp.cubicle ~= point '(2,1)'; name | dream ------+------- Bill | 8400 ``` 請注意這里使用`$1.salary`語法選擇參數行數值的一個字段。 還要注意`SELECT`命令使用`*`表示該表的整個當前行作為復合數值。 表里面的行也可以用表名字引用, 像下面這樣: ``` SELECT name, double_salary(emp) AS dream FROM emp WHERE emp.cubicle ~= point '(2,1)'; ``` 不過這個用法已經廢棄了,因為很容易導致混淆。 有時候用`ROW`構造器動態地構造一個復合參數值也很有用。 比如,我們可以調節傳遞給函數的數據: ``` SELECT name, double_salary(ROW(name, salary*1.1, age, cubicle)) AS dream FROM emp; ``` 也可以寫一個返回復合類型的函數。下面是一個只返回一行的`emp`函數: ``` CREATE FUNCTION new_emp() RETURNS emp AS $$ SELECT text 'None' AS name, 1000.0 AS salary, 25 AS age, point '(2,2)' AS cubicle; $$ LANGUAGE SQL; ``` 在這個例子中我們給每個字段都賦予了一個常量, 當然也可以用任何表達式來代替這些常量。 注意定義函數的兩個重要問題: * 選擇列表的順序必須和與該復合類型相關的表中字段的順序完全一樣。 像上面那樣給字段命名是和系統毫無關系的。 * 你必須對表達式進行類型轉換以匹配復合類型的定義。 否則你將看到下面的錯誤信息: ``` &lt;samp class="literal"&gt;ERROR: function declared to return emp returns varchar instead of text at column 1&lt;/samp&gt; ``` 另外一個定義同樣函數的方法是: ``` CREATE FUNCTION new_emp() RETURNS emp AS $$ SELECT ROW('None', 1000.0, 25, '(2,2)')::emp; $$ LANGUAGE SQL; ``` 這里的`SELECT`只返回對應復合類型的一個單獨字段。 在這種情況下,這么做并沒有任何好處,但是它在某些場合是一個很好用的東西— 比如,需要通過調用另外一個返回所需復合類型數值的函數來計算結果。 我們可以用任何兩種方式直接調用這個函數: ``` SELECT new_emp(); new_emp -------------------------- (None,1000.0,25,"(2,2)") SELECT * FROM new_emp(); name | salary | age | cubicle ------+--------+-----+--------- None | 1000.0 | 25 | (2,2) ``` 第二種方法在[Section 35.4.7](#calibre_link-916)里有更完整的描述。 在使用一個返回復合類型的函數時,你可以用下面的語法從結果中只抽取一個字段: ``` SELECT (new_emp()).name; name ------ None ``` 必須用一對額外的圓括弧防止分析器誤解。 如果省略這對括弧就會看見類似下面這樣的東西: ``` SELECT new_emp().name; ERROR: syntax error at or near "." LINE 1: SELECT new_emp().name; ^ ``` 另外一個選擇是使用函數表示法抽取字段。 解釋這些問題的簡單方法是交互使用`attribute(table)`和 `table.attribute`表示法。 ``` SELECT name(new_emp()); name ------ None ``` ``` --上述語句與下面的這個相同: -- SELECT emp.name AS youngster FROM emp WHERE emp.age < 30; SELECT name(emp) AS youngster FROM emp WHERE age(emp) < 30; youngster ----------- Sam Andy ``` > **Tip:** 函數表示法和字段屬性表示法之間的等效關系讓我們可以使用復合類型上的函數來模擬 "計算得出的字段"。 比如,使用前面的`double_salary(emp)`定義,我們可以寫 > > ``` > SELECT emp.name, emp.double_salary FROM emp; > ``` > > 應用可以直接這么使用而無需明確知道`double_salary`并不是表中一個真實的字段。 同樣也可以模擬視圖上計算出的字段。 > > 因為這種操作,給函數采取單一復合類型參數與復合類型的任何字段名相同是不明智的。 還有一個使用函數返回復合類型的情況是把結果傳遞給另外一個輸入該行類型的函數: ``` CREATE FUNCTION getname(emp) RETURNS text AS $$ SELECT $1.name; $$ LANGUAGE SQL; SELECT getname(new_emp()); getname --------- None (1 row) ``` 還可以把返回復合類型的函數當作一個表函數使用,如[Section 35.4.7](#calibre_link-916)所述。 ## 35.4.4\. 帶輸出參數的SQL函數 描述函數的結果的另外一種方法是把它定義成帶有_輸出參數_的函數,比如: ``` CREATE FUNCTION add_em (IN x int, IN y int, OUT sum int) AS 'SELECT x + y' LANGUAGE SQL; SELECT add_em(3,7); add_em -------- 10 (1 row) ``` 這個版本和[Section 35.4.2](#calibre_link-911)里面 的那個`add_em`版本沒有什么本質的區別。 輸出參數的真正價值在于它提供了定義返回多個字段的函數的便利方法。比如, ``` CREATE FUNCTION sum_n_product (x int, y int, OUT sum int, OUT product int) AS 'SELECT x + y, x * y' LANGUAGE SQL; SELECT * FROM sum_n_product(11,42); sum | product -----+--------- 53 | 462 (1 row) ``` 這里實際發生的事情是我們為函數的結果創建了一個匿名的復合類型。 上面的例子和下面的例子有同樣的最終結果 ``` CREATE TYPE sum_prod AS (sum int, product int); CREATE FUNCTION sum_n_product (int, int) RETURNS sum_prod AS 'SELECT $1 + $2, $1 * $2' LANGUAGE SQL; ``` 不過,不用操心獨立的復合類型定義通常都會很方便。請注意附屬于輸出參數的名稱不僅僅是修飾,但 也決定了匿名復合類型的列名。(如果你為輸出參數而忽略了名稱,則系統將選擇一個自己的名字)。 請注意,從SQL里調用這些函數的時候,輸出參數并未包含在調用參數列表里。 這是因為PostgreSQL認為只有輸入參數定義函數的調用簽名。 這也意味著在類似刪除函數這樣的場合里, 只有輸入參數管用。我們可以用下列命令之一刪除上述函數 ``` DROP FUNCTION sum_n_product (x int, y int, OUT sum int, OUT product int); DROP FUNCTION sum_n_product (int, int); ``` 參數可以被標記為`IN` (缺省), `OUT`, `INOUT`或者`VARIADIC`。 `INOUT`參數同時作為輸入參數(調用參數列表的一部分) 和輸出參數(結果記錄類型的一部分)。 `VARIADIC`參數是輸入參數,但是作為描述文本特殊對待。 ## 35.4.5\. 帶有參數可變數量的SQL SQL函數聲明接受參數可變數量,只要所有"optional" 參數有相同數據類型。可選參數將被作為數組傳遞給函數。函數通過把最后參數作為`VARIADIC` 聲明;這個參數必須聲明為數組類型。比如: ``` CREATE FUNCTION mleast(VARIADIC arr numeric[]) RETURNS numeric AS $$ SELECT min($1[i]) FROM generate_subscripts($1, 1) g(i); $$ LANGUAGE SQL; SELECT mleast(10, -1, 5, 4.4); mleast -------- -1 (1 row) ``` 實際上,達到或者超過`VARIADIC`位置的所有實際參數都被聚集為一維陣列,正如你寫的 ``` SELECT mleast(ARRAY[10, -1, 5, 4.4]); -- doesn't work ``` 你可以不寫,至少它不匹配這個函數定義。標記`VARIADIC`的參數匹配一個或多個元素類型 的發生,而不是固有類型。 有時候可以將已構建數組傳遞給可變參數函數; ``` SELECT mleast(VARIADIC ARRAY[10, -1, 5, 4.4]); ``` 這防止函數的可變參數擴展到它的元素類型,從而使數組參數值正常匹配。 `VARIADIC`只可以附屬于函數調用的最后一個實參。 數組元素的參數產生一個可變的參數作為沒有自己的名字看待。這意味著它是不 可以使用命名參數([Section 4.3](#calibre_link-733))調用一個可變參數函數, 除非你指定`VARIADIC`。例如,這項工作: ``` SELECT mleast(VARIADIC arr := ARRAY[10, -1, 5, 4.4]); ``` 但不是這些: ``` SELECT mleast(arr := 10); SELECT mleast(arr := ARRAY[10, -1, 5, 4.4]); ``` ## 35.4.6\. 具有參數缺省值的SQL函數 函數可以為了部分或全部輸入參數而聲明默認值。 當函數使用不充分的許多實際參數調用函數的時候,插入缺省值。因為參數 只能從實際的參數列表的末尾省略,所有 具有默認值的參數都有默認值。(雖然使用命名參數符號 可以讓這個限制寬松,它仍然是強制的,位置參數符號合理運行。) 比如: ``` CREATE FUNCTION foo(a int, b int DEFAULT 2, c int DEFAULT 3) RETURNS int LANGUAGE SQL AS $$ SELECT $1 + $2 + $3; $$; SELECT foo(10, 20, 30); foo ----- 60 (1 row) SELECT foo(10, 20); foo ----- 33 (1 row) SELECT foo(10); foo ----- 15 (1 row) SELECT foo(); -- fails since there is no default for the first argument ERROR: function foo() does not exist ``` `=`符號也可以用在關鍵字`DEFAULT`的位置。 ## 35.4.7\. 作為表數據源的SQL函數 所有SQL函數都可以在查詢的`FROM`子句里使用。 但是它對于返回復合類型的函數特別有用。如果該函數定義為返回一個基本類型, 那么表函數生成一個單字段表。如果該函數定義為返回一個復合類型, 那么該表函數生成一個該復合類型里每個屬性組成的行。 這里是一個例子: ``` CREATE TABLE foo (fooid int, foosubid int, fooname text); INSERT INTO foo VALUES (1, 1, 'Joe'); INSERT INTO foo VALUES (1, 2, 'Ed'); INSERT INTO foo VALUES (2, 1, 'Mary'); CREATE FUNCTION getfoo(int) RETURNS foo AS $$ SELECT * FROM foo WHERE fooid = $1; $$ LANGUAGE SQL; SELECT *, upper(fooname) FROM getfoo(1) AS t1; fooid | foosubid | fooname | upper -------+----------+---------+------- 1 | 1 | Joe | JOE (1 row) ``` 正如這個例子顯示的那樣,可以像對待一個普通表的字段一樣對待函數的結果字段。 請注意我們只從該函數中獲取了一行。這是因為沒有使用`SETOF`。' 這個問題在下一節講述。 ## 35.4.8\. 返回集合的SQL函數 如果一個SQL函數聲明為返回`SETOF` `_sometype_`, 那么該函數最后的查詢一直執行到結束, 并且它輸出的每一行都被當作該結果集中的一個元素返回。 這個特性通常用于把函數放在`FROM`子句里調用。 此時該函數返回的每一行都成為查詢可見的該表的一行。 比如,假設表`foo`的內容和上面相同,那么: ``` CREATE FUNCTION getfoo(int) RETURNS SETOF foo AS $$ SELECT * FROM foo WHERE fooid = $1; $$ LANGUAGE SQL; SELECT * FROM getfoo(1) AS t1; ``` 將得到: ``` fooid | foosubid | fooname -------+----------+--------- 1 | 1 | Joe 1 | 2 | Ed (2 rows) ``` 它也有可能返回輸出參數定義的列的多行,像這樣: ``` CREATE TABLE tab (y int, z int); INSERT INTO tab VALUES (1, 2), (3, 4), (5, 6), (7, 8); CREATE FUNCTION sum_n_product_with_tab (x int, OUT sum int, OUT product int) RETURNS SETOF record AS $$ SELECT $1 + tab.y, $1 * tab.y FROM tab; $$ LANGUAGE SQL; SELECT * FROM sum_n_product_with_tab(10); sum | product -----+--------- 11 | 10 13 | 30 15 | 50 17 | 70 (4 rows) ``` 這里關鍵的一點是你必須寫`RETURNS SETOF record`表明函數返回多行而不是一行。 如果只有一個輸出參數,寫參數類型而不是`record`。 它通過調用多次設置返回函數構建一個查詢結果經常是有用的,為了每個參數調用 一個表或查詢連續的行。這樣做的最佳方法是使用`LATERAL`關鍵字, 在[Section 7.2.1.5](#calibre_link-970)中描述的。 這里是一個例子,使用設置返回函數來枚舉樹結構元素: ``` SELECT * FROM nodes; name | parent -----------+-------- Top | Child1 | Top Child2 | Top Child3 | Top SubChild1 | Child1 SubChild2 | Child1 (6 rows) CREATE FUNCTION listchildren(text) RETURNS SETOF text AS $$ SELECT name FROM nodes WHERE parent = $1 $$ LANGUAGE SQL STABLE; SELECT * FROM listchildren('Top'); listchildren -------------- Child1 Child2 Child3 (3 rows) SELECT name, child FROM nodes, LATERAL listchildren(name) AS child; name | child --------+----------- Top | Child1 Top | Child2 Top | Child3 Child1 | SubChild1 Child1 | SubChild2 (5 rows) ``` 這個例子不做任何事情,我們不能做一個簡單的連接,但在更復雜的計算中,選擇把 一些工作放入一個函數中是很方便的。 目前,返回集合的函數也可以在一個查詢的選擇列表里調用。對于該查詢自己生成的每一行,都會調用這個返回集合的函數,并且對于該函數的結果集中的每個元素都會生成一個輸出行。不過,這個功能已經廢棄了,在將來的版本中可能會被刪除。下面就是一個在選擇列表中使用返回集合的函數的例子: ``` SELECT listchildren('Top'); listchildren -------------- Child1 Child2 Child3 (3 rows) SELECT name, listchildren(name) FROM nodes; name | listchildren --------+-------------- Top | Child1 Top | Child2 Top | Child3 Child1 | SubChild1 Child1 | SubChild2 (5 rows) ``` 請注意,在最后的`SELECT`里沒有出現`Child2`, `Child3`等行。 這是因為`listchildren`為這些參數返回一個空集合, 因此不生成任何結果行。 當使用`LATERAL`語法時,這同從內部鏈接到函數結果行為是一樣的。 > **Note:** 如果函數的最后命令是`INSERT`, `UPDATE`, 或者帶有`RETURNING`的`DELETE`,則命令將總是執行完成,即使 函數不被聲明為`SETOF`或者調用查詢不抓取所有結果行。 任何通過`RETURNING`子句產生的額外行靜靜地被刪除,但是 仍然產生命令表修改(都是從函數返回前完成)。 > **Note:** 在選擇列表中使用設置返回函數而不是`FROM`子句的關鍵問題是將一個以上的設置 返回函數放在同一個選擇列表中是不明智的。如果你將輸出行數等同于 通過每個設置返回函數產生的行數的最小公倍數,你實際得到了什么。 當調用多個設置返回函數并且往往替代使用的時候, `LATERAL`語法很少產生令人驚訝的結果。 ## 35.4.9\. 返回`TABLE`的SQL函數 還有另一種方式來聲明返回集合的函數, 它是利用語法`RETURNS TABLE(``_columns_`)。 這相當于使用一個或多個`OUT`參數加上 標記函數作為返回`SETOF record`(或者`SETOF`一個輸出參數的類型,視 情況而定)。這個符號是在最近的SQL標準版本中規定的,因此可能比使用`SETOF`更便捷。 比如,前面的和與乘積的例子可以這樣做: ``` CREATE FUNCTION sum_n_product_with_tab (x int) RETURNS TABLE(sum int, product int) AS $$ SELECT $1 + tab.y, $1 * tab.y FROM tab; $$ LANGUAGE SQL; ``` 不允許使用明確的帶有`RETURNS TABLE`標記的 `OUT`或者`INOUT`參數— 你必須將所有輸出參數放在 `TABLE`列表中。 ## 35.4.10\. 多態SQL函數 SQL函數可以聲明為接受并返回多態類型`anyelement`, `anyarray`, `anynonarray`, `anyenum`和`anyrange`。 參閱[Section 35.2.5](#calibre_link-909)獲取有關多態函數的更多細節。 下面是一個多態的函數`make_array`, 它從兩個任意數據類型元素中建立一個數組: ``` CREATE FUNCTION make_array(anyelement, anyelement) RETURNS anyarray AS $$ SELECT ARRAY[$1, $2]; $$ LANGUAGE SQL; SELECT make_array(1, 2) AS intarray, make_array('a'::text, 'b') AS textarray; intarray | textarray ----------+----------- {1,2} | {a,b} (1 row) ``` 請注意使用了類型轉換`'a'::text`聲明參數是`text`類型。 如果參數只是一個字符串文本,這是必須的, 否則它就會被當作`unknown`類型。 因為`unknown`不是一種有效的類型,所以如果沒有類型轉換, 就會看到類似下面這樣的錯誤信息: ``` <samp class="literal">ERROR: could not determine polymorphic type because input has type "unknown"</samp> ``` 允許含有多態參數的函數返回一個固定類型, 但是反過來不行。比如: ``` CREATE FUNCTION is_greater(anyelement, anyelement) RETURNS boolean AS $$ SELECT $1 > $2; $$ LANGUAGE SQL; SELECT is_greater(1, 2); is_greater ------------ f (1 row) CREATE FUNCTION invalid_func() RETURNS anyelement AS $$ SELECT 1; $$ LANGUAGE SQL; ERROR: cannot determine result data type DETAIL: A function returning a polymorphic type must have at least one polymorphic argument. ``` 多態性也可以用于那些含有輸出參數的函數。比如: ``` CREATE FUNCTION dup (f1 anyelement, OUT f2 anyelement, OUT f3 anyarray) AS 'select $1, array[$1,$1]' LANGUAGE SQL; SELECT * FROM dup(22); f2 | f3 ----+--------- 22 | {22,22} (1 row) ``` 多態性也可以使用可變參數函數。比如: ``` CREATE FUNCTION anyleast (VARIADIC anyarray) RETURNS anyelement AS $$ SELECT min($1[i]) FROM generate_subscripts($1, 1) g(i); $$ LANGUAGE SQL; SELECT anyleast(10, -1, 5, 4); anyleast ---------- -1 (1 row) SELECT anyleast('abc'::text, 'def'); anyleast ---------- abc (1 row) CREATE FUNCTION concat_values(text, VARIADIC anyarray) RETURNS text AS $$ SELECT array_to_string($2, $1); $$ LANGUAGE SQL; SELECT concat_values('|', 1, 4, 2); concat_values --------------- 1|4|2 (1 row) ``` ## 35.4.11\. 帶有排序規則的SQL函數 當一個SQL函數具有一個或多個collatable數據類型的參數, 排序規則認同每個函數調用依賴 于分配給實際參數的排序規則,正如[Section 22.2](#calibre_link-667)描述的。如果 一個排序規則成功地被識別(即不存在參數之間的隱式排序規則的沖突) 然后所有的collatable參數作為 含蓄的排序規則對待。這會影響函數內排序規則區分操作行為。 例如,使用上文描述的 `anyleast`,結果為 ``` SELECT anyleast('abc'::text, 'ABC'); ``` 將依賴于數據庫的缺省排序規則。在`C`中結果將是`ABC`, 但是在許多其他區域中它將是`abc`。使用的排序規則通過添加`COLLATE` 子句強制給任何參數,比如 ``` SELECT anyleast('abc'::text, 'ABC' COLLATE "C"); ``` 另外,如果你希望函數操作特定的排序規則不管稱為什么, 作為需要插入`COLLATE` 子句到函數定義中,`anyleast`的版本可能總是使用 `en_US`區域來比較字符串: ``` CREATE FUNCTION anyleast (VARIADIC anyarray) RETURNS anyelement AS $$ SELECT min($1[i] COLLATE "en_US") FROM generate_subscripts($1, 1) g(i); $$ LANGUAGE SQL; ``` 但是請注意如果適用于非-collatable數據類型,則將拋出一個錯誤。 如果在實際參數之間沒有識別通用排序規則, 那么一個SQL函數將其參數作為數據類型 的默認排序規則(通常是數據庫的默認排序規則,但不同于域類型參數)。 collatable參數操作可以被認為是多態的有限形式,只適用于文本數據類型。
                  <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>

                              哎呀哎呀视频在线观看