| PostgreSQL 7.4 文檔 | ||||
|---|---|---|---|---|
| Prev | Fast Backward | Chapter 37. PL/pgSQL - SQL 過程語言 | Fast Forward | Next |
所有在塊裡使用的變量都必須在一個塊的聲明段裡聲明。 (唯一的例外是一個FOR循環裡的循環變量是在一個整數範圍內迭代的,被自動聲明為整數變量。)
PL/pgSQL變量可以由任意的 SQL 數據類型,比如 integer,varchar 和 char。
下面是一些變量聲明的例子︰
user_id integer; quantity numeric(5); url varchar; myrow tablename%ROWTYPE; myfield tablename.fieldname%TYPE; arow RECORD;
一個變量聲明的一般性語法是︰
name [ CONSTANT ] type [ NOT NULL ] [ { DEFAULT | := } expression ];
如果給出了DEFAULT子句,那麼它聲明了在進入該塊的時候賦予該變量的初始值。 如果沒有給出DEFAULT子句,那麼該變量初始化為 SQL 空值。 CONSTANT選項避免了該變量被賦值,這樣其數值在該塊的範圍內保持常量。 如果聲明了NOT NULL,那麼賦予NULL數值將導致一個運行時錯誤。 所以所有聲明為NOT NULL的變量還必須聲明一個非空的缺省值。
缺省值是在每次進入該塊的時候計算的。因此,如果把 'now' 賦予一個類型為 timestamp 的變量會令變量擁有函數實際調用的時間,而不是函數預編譯的時間。
例子︰
quantity integer DEFAULT 32; url varchar := ''http://mysite.com''; user_id CONSTANT integer := 10;
name ALIAS FOR $n;
傳遞給函數的參數都是用 $1,$2,等等這樣的標識符。 為了增加可讀性,我們可以為 $n 參數名聲明別名。 然後別名或者數字標識符都可以指向參數值。一些例子:
CREATE FUNCTION sales_tax(REAL) RETURNS real AS '
DECLARE
subtotal ALIAS FOR $1;
BEGIN
RETURN subtotal * 0.06;
END;
' LANGUAGE plpgsql;
CREATE FUNCTION instr(varchar,integer) RETURNS integer AS '
DECLARE
v_string ALIAS FOR $1;
index ALIAS FOR $2;
BEGIN
-- 這裡放一些計算
END;
' LANGUAGE plpgsql;
CREATE FUNCTION concat_selected_fields(tablename) RETURNS text AS '
DECLARE
in_t ALIAS FOR $1;
BEGIN
RETURN in_t.f1 || in_t.f3 || in_t.f5 || in_t.f7;
END;
' LANGUAGE plpgsql;
如果一個 PL/pgSQL 函數的返回類型聲明為一個多態類型 (anyelement 或者 anyarray),那麼就會創建一個特殊的參數, $0。它的數據類型是函數的實際返回類型,和從實際輸入類型推導推導類型一樣 (參閱 Section 33.2.5)。 這樣就允許函數訪問它的實際返回類型,像 Section 37.4.2 裡顯示的那樣。 $0 初始化為空,並且可以被函數修改,所以,如果需要,它可以用于保存返回值, 雖然這並非必須的。$0 還可以給予一個別名。比如,這個函數可以在任何有 + 操作符的數據類型上運轉:
CREATE FUNCTION add_three_values(anyelement, anyelement, anyelement)
RETURNS anyelement AS '
DECLARE
result ALIAS FOR $0;
first ALIAS FOR $1;
second ALIAS FOR $2;
third ALIAS FOR $3;
BEGIN
result := first + second + third;
RETURN result;
END;
' LANGUAGE plpgsql;
variable%TYPE
%TYPE 提供一個變量或者表字段的數據類型。 你可以用這個聲明將要保存數據庫數值的變量。比如,假如你在 users 表裡面有一個字段叫 user_id。要聲明一個和 users.user_id 類型相同的變量,你可以寫:
user_id users.user_id%TYPE;
通過使用 %TYPE,你必須知道你引用的結構的數據類型, 並且,最重要的是,如果被引用項的數據類型在將來變化了(比如:你把 user_id 的類型從 integer 改成 real),你也不需要修改你的函數定義。
%TYPE 對多態的函數特別有用,因為內部變量的數據類型可能在不同調用中是不一樣的。 我們可以通過給函數的參數或者結果佔位符附加 %TYPE 的方法來創建合適的變量。
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) 這種類型字段的尺寸和精度。
這裡是一個使用復合類型的例子:
CREATE FUNCTION use_two_tables(tablename) RETURNS text AS '
DECLARE
in_t ALIAS FOR $1;
use_t table2name%ROWTYPE;
BEGIN
SELECT * INTO use_t FROM table2name WHERE ... ;
RETURN in_t.f1 || use_t.f3 || in_t.f5 || use_t.f7;
END;
' LANGUAGE plpgsql;
name RECORD;
紀錄變量類似行類型變量,但是它們沒有預定義的結構。 它們在SELECT或者FOR命令中獲取實際的行結構。 一個行變量的子結構可以在每次賦值的時候改變。 這樣做的一個結果是:在一個記錄變量被賦予數值之前,它沒有子結構, 並且任何對其中的數據域進行訪問的企圖都將產生一個運行時錯誤。
請注意 RECORD 不是真正的數據類型,只是一個佔位符。 我們還應該意識到在把一個 PL/pgSQL 函數聲明為返回record類型的時候, 它喝一個記錄變量的概念並不完全相同,即使這個函數可能使用一個記錄變量保存它的結果也如此。 在兩種情況下,在書寫函數的時候,實際的行結構都是不知道的,但是對于返回 record 的函數來說, 實際的結構實在調用它的查詢被分析的時候決定的,而行變量可以在運行中改變其行結構。
RENAME oldname TO newname;
你可以用 RENAME 聲明修改一個變量,記錄或者行的名字。 如果 NEW 或者 OLD 在個觸發器過程裡被另外一個名字引用, 那麼這個東西就很有用。又見 ALIAS。
例子︰
RENAME id TO user_id; RENAME this_var TO that_var;
注意: RENAME 在PostgreSQL7.3 裡好像有問題。修補這個毛病的優先級比較低, 因為 ALIAS 覆蓋了大多數 RENAME 的實際用途。