開發 PL/pgSQL 的一個好方法是使用您選擇的文字編輯器來建立函式,並在另一個視窗中使用 psql 來載入和測試這些函式。如果您這樣做,最好使用 CREATE OR REPLACE FUNCTION
來編寫函式。這樣您就可以簡單地重新載入檔案來更新函式定義。例如:
CREATE OR REPLACE FUNCTION testfunc(integer) RETURNS integer AS $$ .... $$ LANGUAGE plpgsql;
在執行 psql 時,您可以使用以下命令載入或重新載入此類函式定義檔案:
\i filename.sql
然後立即發出 SQL 命令來測試該函式。
使用支援過程語言開發的 GUI 資料庫訪問工具是開發 PL/pgSQL 的另一種好方法。pgAdmin 就是這類工具的一個例子,儘管還有其他工具。這些工具通常提供方便的功能,例如轉義單引號,以及更輕鬆地重新建立和除錯函式。
PL/pgSQL 函式的程式碼在 CREATE FUNCTION
中被指定為字串字面量。如果您以普通方式編寫帶周圍單引號的字串字面量,那麼函式體內的任何單引號都必須加倍;同樣,任何反斜槓都必須加倍(假設使用了跳脫字元串語法)。加倍引號至少是乏味的,在更復雜的情況下,程式碼會變得難以理解,因為您很容易發現需要半打或更多的相鄰引號。建議您改用“美元定界字串”(dollar-quoted)字面量來編寫函式體(參見 4.1.2.4 節)。在美元定界的方法中,您永遠不需要加倍任何引號,而是注意為所需的每個巢狀級別選擇不同的美元定界字串分隔符。例如,您可以將 CREATE FUNCTION
命令寫成:
CREATE OR REPLACE FUNCTION testfunc(integer) RETURNS integer AS $PROC$ .... $PROC$ LANGUAGE plpgsql;
在此之中,您可以使用引號來表示 SQL 命令中的簡單字面字串,並使用 $$
來分隔您正在組裝為字串的 SQL 命令片段。如果您需要引用包含 $$
的文字,您可以使用 $Q$
,依此類推。
以下圖表顯示了在不使用美元定界字串時編寫引號所需執行的操作。當將舊的(非美元定界)程式碼轉換為更易讀的內容時,它可能會很有用。
例如,用於開始和結束函式體
CREATE FUNCTION foo() RETURNS integer AS ' .... ' LANGUAGE plpgsql;
在單引號包圍的函式體內,任何地方的引號必須成對出現。
例如,用於函式體內的字串字面量
a_output := ''Blah''; SELECT * FROM users WHERE f_name=''foobar'';
在美元定界的方法中,您只需寫:
a_output := 'Blah'; SELECT * FROM users WHERE f_name='foobar';
無論哪種情況,PL/pgSQL 解析器實際看到的都是這樣。
當您在函式體內的字串常量中需要一個單引號時,例如
a_output := a_output || '' AND name LIKE ''''foobar'''' AND xyz''
實際附加到 a_output
的值將是:AND name LIKE 'foobar' AND xyz
。
在美元定界的方法中,您將寫:
a_output := a_output || $$ AND name LIKE 'foobar' AND xyz$$
確保此處的任何美元定界字串分隔符不是 $$
。
當函式體內的字串中的單引號緊鄰該字串常量末尾時,例如
a_output := a_output || '' AND name LIKE ''''foobar''''''
然後附加到 a_output
的值將是:AND name LIKE 'foobar'
。
在美元定界的方法中,這將變成:
a_output := a_output || $$ AND name LIKE 'foobar'$$
當您想在字串常量中放置兩個單引號(這佔用了 8 個引號),並且這又緊鄰該字串常量末尾(另外 2 個)。您可能只需要在編寫生成其他函式的函式時才需要,如 示例 41.10 所示。例如:
a_output := a_output || '' if v_'' || referrer_keys.kind || '' like '''''''''' || referrer_keys.key_string || '''''''''' then return '''''' || referrer_keys.referrer_type || ''''''; end if;'';
然後 a_output
的值將是:
if v_... like ''...'' then return ''...''; end if;
在美元定界的方法中,這將變成:
a_output := a_output || $$ if v_$$ || referrer_keys.kind || $$ like '$$ || referrer_keys.key_string || $$' then return '$$ || referrer_keys.referrer_type || $$'; end if;$$;
假設我們只需要將單引號放入 a_output
中,因為在使用前它將被重新引用。
為了幫助使用者在出現簡單但常見的問題之前發現它們,PL/pgSQL 提供了額外的檢查
。啟用後,根據配置,它們可以用於在函式編譯期間發出 WARNING
或 ERROR
。收到 WARNING
的函式可以執行而不會產生進一步的訊息,因此建議您在一個單獨的開發環境中進行測試。
建議在開發和/或測試環境中將 plpgsql.extra_warnings
或 plpgsql.extra_errors
(根據需要)設定為 "all"
。
這些額外的檢查透過配置變數 plpgsql.extra_warnings
(用於警告)和 plpgsql.extra_errors
(用於錯誤)來啟用。兩者都可以設定為逗號分隔的檢查列表、"none"
或 "all"
。預設值為 "none"
。目前可用的檢查列表包括:
shadowed_variables
#檢查宣告是否覆蓋了先前定義的變數。
strict_multi_assignment
#PL/pgSQL 中的某些命令允許一次將值賦給多個變數,例如 SELECT INTO
。通常,目標變數的數量和源變數的數量應匹配,儘管 PL/pgSQL 會為缺失的值使用 NULL
,並忽略多餘的變數。啟用此檢查將導致 PL/pgSQL 在目標變數和源變數的數量不同時引發 WARNING
或 ERROR
。
too_many_rows
#啟用此檢查將導致 PL/pgSQL 檢查在使用 INTO
子句時,給定查詢是否返回了多於一行。由於 INTO
語句只會使用一行,因此查詢返回多行通常效率低下和/或不確定,因此很可能是一個錯誤。
以下示例顯示了將 plpgsql.extra_warnings
設定為 shadowed_variables
的效果:
SET plpgsql.extra_warnings TO 'shadowed_variables'; CREATE FUNCTION foo(f1 int) RETURNS int AS $$ DECLARE f1 int; BEGIN RETURN f1; END; $$ LANGUAGE plpgsql; WARNING: variable "f1" shadows a previously defined variable LINE 3: f1 int; ^ CREATE FUNCTION
以下示例顯示了將 plpgsql.extra_warnings
設定為 strict_multi_assignment
的效果:
SET plpgsql.extra_warnings TO 'strict_multi_assignment'; CREATE OR REPLACE FUNCTION public.foo() RETURNS void LANGUAGE plpgsql AS $$ DECLARE x int; y int; BEGIN SELECT 1 INTO x, y; SELECT 1, 2 INTO x, y; SELECT 1, 2, 3 INTO x, y; END; $$; SELECT foo(); WARNING: number of source and target fields in assignment does not match DETAIL: strict_multi_assignment check of extra_warnings is active. HINT: Make sure the query returns the exact list of columns. WARNING: number of source and target fields in assignment does not match DETAIL: strict_multi_assignment check of extra_warnings is active. HINT: Make sure the query returns the exact list of columns. foo ----- (1 row)
如果您在文件中看到任何不正確的內容、與您在使用特定功能時的經驗不符或需要進一步說明的內容,請使用此表單來報告文件問題。