<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之旅 廣告
                # 40.3\. 聲明 所有在塊里使用的變量都必須在一個塊的聲明段里聲明。 唯一的例外是一個`FOR`循環里的循環變量是在一個整數范圍內迭代的, 被自動聲明為整數變量。并且同樣從游標結果中`FOR`循環迭代的循環變量自動被聲明為記錄變量。 PL/pgSQL變量可以使用任意的SQL數據類型,比如`integer`, `varchar`和`char`等等。 下面是一些變量聲明的例子: ``` user_id integer; quantity numeric(5); url varchar; myrow tablename%ROWTYPE; myfield tablename.columnname%TYPE; arow RECORD; ``` 一個變量聲明的一般性語法是: ``` _name_ [ CONSTANT ] _type_ [ COLLATE `_collation_name_` ] [ NOT NULL ] [ { DEFAULT | := } `_expression_` ]; ``` 如果給出了`DEFAULT`子句,那么它聲明了在進入該塊的時候賦予該變量的初始值。 如果沒有給出`DEFAULT`子句,那么該變量初始化為SQL NULL。 `CONSTANT`選項避免了該變量被賦值,這樣其數值在該塊的范圍內保持常量。 `COLLATE`選項聲明變量使用的排序規則(參見[Section 40.3.6](#calibre_link-1671))。 如果聲明了`NOT NULL`,那么賦予NULL的數值將運行時導致錯誤。 所以所有聲明為`NOT NULL`的變量還必須聲明一個非空的缺省值。 缺省值是在每次進入該塊的時候計算的,而不是每次調用函數時。 因此,如果把`now()`賦予一個類型為`timestamp`的變量會令變量擁有函數實際調用的時間, 而不是函數預編譯的時間。 例如: ``` quantity integer DEFAULT 32; url varchar := 'http://mysite.com'; user_id CONSTANT integer := 10; ``` ## 40.3.1\. 聲明函數參數 傳遞給函數的參數都是用`$1`, `$2`等等這樣的標識符。 為了增加可讀性,可以為`$``_n_`參數名聲明別名。 然后別名或者數字標識符都可以指向參數值。 有兩種創建別名的方法,比較好的是在`CREATE FUNCTION`命令里給出參數名,比如: ``` CREATE FUNCTION sales_tax(subtotal real) RETURNS real AS $$ BEGIN RETURN subtotal * 0.06; END; $$ LANGUAGE plpgsql; ``` 另外一個方法(也是PostgreSQL 8.0以前的唯一的方法), 是使用聲明語法明確聲明別名: ``` _name_ ALIAS FOR $_n_; ``` 這個風格的同一個例子看起來像下面這樣: ``` CREATE FUNCTION sales_tax(real) RETURNS real AS $$ DECLARE subtotal ALIAS FOR $1; BEGIN RETURN subtotal * 0.06; END; $$ LANGUAGE plpgsql; ``` > **Note:** 這兩個例子的作用不是完全一致的。 在第一個例子中,`subtotal`可以作為`sales_tax.subtotal`被引用, 而在第二個例子中是不可以的。(我們在內部塊中附加標簽,反而`subtotal`符合這個標簽)。 更多例子: ``` CREATE FUNCTION instr(varchar, integer) RETURNS integer AS $$ DECLARE v_string ALIAS FOR $1; index ALIAS FOR $2; BEGIN 這里放一些使用 v_string 和 index 的計算 END; $$ LANGUAGE plpgsql; CREATE FUNCTION concat_selected_fields(in_t sometablename) RETURNS text AS $$ BEGIN RETURN in_t.f1 || in_t.f3 || in_t.f5 || in_t.f7; END; $$ LANGUAGE plpgsql; ``` 如果一個PL/pgSQL函數聲明中含有輸出參數, 那么就會給予輸出參數`$``_n_`的名字以及可選的別名, 方法和其它正常輸入參數一樣。一個輸出參數實際上是初始值為 NULL 的變量; 在函數執行的過程中,應該給它賦值。 該參數的最后數值是返回的東西。比如, 銷售額-稅費的例子也可以這么做: ``` CREATE FUNCTION sales_tax(subtotal real, OUT tax real) AS $$ BEGIN tax := subtotal * 0.06; END; $$ LANGUAGE plpgsql; ``` 請注意忽略了`RETURNS real` —當然也可以包含它,不過這樣就顯得多余了。 輸出參數在返回多個數值的時候非常有用。一個簡單的例子是: ``` CREATE FUNCTION sum_n_product(x int, y int, OUT sum int, OUT prod int) AS $$ BEGIN sum := x + y; prod := x * y; END; $$ LANGUAGE plpgsql; ``` 正如在[Section 35.4.4](#calibre_link-913)里面討論的, 這樣做實際上為函數的結果創建了一個匿名的記錄類型。如果給出一個 `RETURNS`子句,那么它就必須使用 `RETURNS record`。 另一個聲明PL/pgSQL函數的方法是使用 `RETURNS TABLE`,例如: ``` CREATE FUNCTION extended_sales(p_itemno int) RETURNS TABLE(quantity int, total numeric) AS $$ BEGIN RETURN QUERY SELECT quantity, quantity * price FROM sales WHERE itemno = p_itemno; END; $$ LANGUAGE plpgsql; ``` 這完全等價于聲明一個或多個`OUT`參數, 并且聲明`RETURNS SETOF``_sometype_`。 如果將PL/pgSQL函數的返回類型聲明為多態類型 (`anyelement`, `anyarray`, `anynonarray`, `anyenum`, 或者`anyrange`), 那么就會創建一個特殊的`$0`參數, 它的數據類型是函數的實際返回類型, 和從實際輸入類型的推導類型一樣 (參閱[Section 35.2.5](#calibre_link-909))。這樣就允許函數像 [Section 40.3.3](#calibre_link-1668)里顯示的那樣訪問它的實際返回類型。 `$0`初始化為空,并且可以被函數修改, 所以,如果需要,它可以用于保存返回值,雖然這并非必須。 `$0`還可以給予一個別名。 比如,這個函數可以在任何有`+`操作符的數據類型上運轉: ``` CREATE FUNCTION add_three_values(v1 anyelement, v2 anyelement, v3 anyelement) RETURNS anyelement AS $$ DECLARE result ALIAS FOR $0; BEGIN result := v1 + v2 + v3; RETURN result; END; $$ LANGUAGE plpgsql; ``` 通過將一個或多個輸出參數聲明為多態類型,可以達到相同的效果。 在這種情況下,特殊的參數`$0`不會使用;輸出參數自己起這個作用。比如: ``` CREATE FUNCTION add_three_values(v1 anyelement, v2 anyelement, v3 anyelement, OUT sum anyelement) AS $$ BEGIN sum := v1 + v2 + v3; END; $$ LANGUAGE plpgsql; ``` ## 40.3.2\. `別名` ``` _newname_ ALIAS FOR _oldname_; ``` `別名`語法比在之前章節提到的更普遍:可以為任何一個參數聲明別名,而不僅僅只是對函數。 這樣做的主要目的是為已經有名字的參數重新定義一個名字,例如觸發器中的`NEW` 或者`OLD`。 例如: ``` DECLARE prior ALIAS FOR old; updated ALIAS FOR new; ``` 由于`ALIAS`創建了兩種不同的方式來命名相同的對象,因此,無限制的使用會造成混淆。 最好是在重寫預定名稱時使用。 ## 40.3.3\. 拷貝類型 ``` _variable_%TYPE ``` `%TYPE`提供一個變量或者表字段的數據類型。 你可以用這個聲明將要保存數據庫數值的變量。比如,假如你 在`users`表里面有一個`user_id`字段。 要聲明一個和`users.user_id`類型相同的變量,可以這樣寫: ``` user_id users.user_id%TYPE; ``` 通過使用`%TYPE`,你無需知道引用的結構的數據類型,并且,最重要的是, 如果被引用項的數據類型在將來變化了(比如把`user_id`的類型從`integer` 改成`real`),也不需要修改函數定義。 `%TYPE`對多態函數特別有用,因為內部變量的數據類型可能在不同調用中不一樣。 可以通過給函數的參數或者結果占位符附加`%TYPE`的方法來創建合適的變量。 ## 40.3.4\. 行類型 ``` _name_ _table_name_%ROWTYPE; _name_ _composite_type_name_; ``` 一個復合類型變量叫做_行_變量(或者_row-type_變量)。 這樣的一個變量可以保存一次`SELECT`或者`FOR`命令結果的完整一行, 只要命令的字段集匹配該變量聲明的類型。 行數值的字段使用點表示法訪問,比如`rowvar.field`。 行變量可以聲明為和一個現有的表或者視圖的行類型相同, 方法是使用`_table_name_``%ROWTYPE`表示法; 或者你也可以聲明它的類型是一個復合類型的名字。 因為每個表都有一個相關聯的同名數據類型,在PostgreSQL里實在是無所謂你寫不寫`%ROWTYPE`。但是有`%ROWTYPE`的形式移植性更好。 函數的參數可以是復合類型(表的完整行)。 這個時候,對應的標識符`$``_n_`將是一個行變量, 并且可以從中選取字段,比如`$1.user_id`。 在一個行類型的變量中,只可以訪問用戶定義的表中行的屬性,不包括OID 或者其它系統屬性(因為該行可能來自一個視圖)。 該行類型的數據域繼承表中像`char(``_n_`) 這種類型字段的尺寸和精度。 這里是一個使用復合類型的例子。`table1` 和`table2`是現有的表,至少包含代碼中提到的字段: ``` CREATE FUNCTION merge_fields(t_row table1) RETURNS text AS $$ DECLARE t2_row table2%ROWTYPE; BEGIN SELECT * INTO t2_row FROM table2 WHERE ... ; RETURN t_row.f1 || t2_row.f3 || t_row.f5 || t2_row.f7; END; $$ LANGUAGE plpgsql; SELECT merge_fields(t.*) FROM table1 t WHERE ... ; ``` ## 40.3.5\. 記錄類型 ``` _name_ RECORD; ``` 紀錄變量類似行類型變量,但是它們沒有預定義的結構。它們在`SELECT` 或者`FOR`命令中獲取實際的行結構。 一個行變量的子結構可以在每次賦值的時候改變。 這樣做的一個結果是:在一個記錄變量被賦予數值之前,它沒有子結構, 并且任何對其中的數據域進行訪問的企圖都將產生一個運行時錯誤。 請注意,`RECORD`不是真正的數據類型,只是一個占位符。 還應該意識到在把一個PL/pgSQL函數聲明為返回`record`類型的時候,它和一個記錄變量的概念并不完全相同, 即使這個函數可能使用一個記錄變量保存它的結果也如此。 在這兩種情況下書寫函數的時候,實際的行結構都是未知的, 但是對于返回`record`的函數來說, 實際的結構是在調用它的查詢被分析的時候決定的,而行變量可以在運行中改變其行結構。 ## 40.3.6\. PL/pgSQL變量的排序規則 當PL/pgSQL函數有排序規則數據類型的一個以上的參數時, 排序規則確定每個函數調用依賴于分配給實際參數的排序規則,正如[Section 22.2](#calibre_link-667)。 如果排序規則成功被識別(比如,在這些參數之間沒有隱式排序規則沖突),那么所有 排序規則參數作為有隱式排序規則對待。 這將影響函數內部排序規則敏感操作行為。比如,考慮: ``` CREATE FUNCTION less_than(a text, b text) RETURNS boolean AS $$ BEGIN RETURN a < b; END; $$ LANGUAGE plpgsql; SELECT less_than(text_field_1, text_field_2) FROM table1; SELECT less_than(text_field_1, text_field_2 COLLATE "C") FROM table1; ``` `less_than`的第一次使用出于比較將使用`text_field_1`和 `text_field_2`的通用排序規則,然而第二次使用將使用`C` 排序規則。 此外,被識別的排序規則也被假定為任何局部變量是collatable類型的排序規則。 因此這個函數沒有任何不同,如果它被寫為: ``` CREATE FUNCTION less_than(a text, b text) RETURNS boolean AS $$ DECLARE local_a text := a; local_b text := b; BEGIN RETURN local_a < local_b; END; $$ LANGUAGE plpgsql; ``` 如果沒有collatable數據類型的參數,或者沒有通用排序規則可以識別他們,那么參數和局部變量 使用數據類型的缺省排序規則(這往往是數據庫的缺省排序規則,但是可能不同于域類型變量)。 collatable數據類型的局部變量可以有與聲明中包含`COLLATE`選項的相關聯的不同排序規則。 比如, ``` DECLARE local_a text COLLATE "en_US"; ``` 這個選項覆蓋排序規則,否則按照上述規則給定變量。 同時,如果期望強迫在特定操作中使用特定排序規則,當然明確的`COLLATE`子句可以寫 在函數中。 ``` CREATE FUNCTION less_than_c(a text, b text) RETURNS boolean AS $$ BEGIN RETURN a < b COLLATE "C"; END; $$ LANGUAGE plpgsql; ``` 這將重寫與表列,參數,或者表達式中使用的局部變量相關聯的排序規則,正如在純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>

                              哎呀哎呀视频在线观看