W3Cschool
恭喜您成為首批注冊(cè)用戶
獲得88經(jīng)驗(yàn)值獎(jiǎng)勵(lì)
在PL/pgSQL中進(jìn)行開(kāi)發(fā)的一種好方法是使用你自己選擇的文本編輯器來(lái)創(chuàng)建函數(shù),并且在另一個(gè)窗口中使用psql來(lái)載入并且測(cè)試那些函數(shù)。如果你正在這樣做,使用CREATE OR REPLACE FUNCTION
來(lái)編寫(xiě)函數(shù)是一個(gè)好主意。用那種方式你只需要重載該文件來(lái)更新函數(shù)的定義。例如:
CREATE OR REPLACE FUNCTION testfunc(integer) RETURNS integer AS $$
....
$$ LANGUAGE plpgsql;
在運(yùn)行psql期間,你可以用下面的命令載入或者重載這樣一個(gè)函數(shù)定義文件:
\i filename.sql
并且接著立即發(fā)出 SQL 命令來(lái)測(cè)試該函數(shù)。
另一種在PL/pgSQL中開(kāi)發(fā)的方式是用一個(gè) GUI 數(shù)據(jù)庫(kù)訪問(wèn)工具,它能方便對(duì)過(guò)程語(yǔ)言的開(kāi)發(fā)。這種工具的一個(gè)例子是pgAdmin。這些工具通常提供方便的特性,例如轉(zhuǎn)義單引號(hào)以及便于重新創(chuàng)建和調(diào)試函數(shù)。
一個(gè)PL/pgSQL函數(shù)的代碼在一個(gè)CREATE FUNCTION
中被指定為一個(gè)字符串。如果你用通常的方式把該字符串寫(xiě)在單引號(hào)中間,那么該函數(shù)體中的任何單引號(hào)都必須被雙寫(xiě);同樣任何反斜線也必須被雙寫(xiě)(假定使用了轉(zhuǎn)義字符串語(yǔ)法)。雙寫(xiě)引號(hào)最多有點(diǎn)冗長(zhǎng),并且在更復(fù)雜的情況中代碼會(huì)變得完全無(wú)法理解,因?yàn)槟愫苋菀装l(fā)現(xiàn)你需要半打或者更多相鄰的引號(hào)。我們推薦你轉(zhuǎn)而把函數(shù)體寫(xiě)成一個(gè)
“美元引用”的字符串(見(jiàn)第 4.1.2.4 節(jié))。在美元引用方法中,你從不需要雙寫(xiě)任何引號(hào)。但是要注意為你需要的每一層嵌套選擇一個(gè)不同的美元引用定界符。例如,你可能把CREATE FUNCTION
命令寫(xiě)成:
CREATE OR REPLACE FUNCTION testfunc(integer) RETURNS integer AS $PROC$ .... $PROC$ LANGUAGE plpgsql;
在這里面,你可以在 SQL 命令中為簡(jiǎn)單字符串使用引號(hào)并且用$$
來(lái)界定被你組裝成字符串的 SQL 命令片段。如果你需要引用包括$$
的文本,你可以使用$Q$
等等。
下列圖表展示了在寫(xiě)沒(méi)有美元引用的引號(hào)時(shí)需要做什么。在將之前用美元引用的代碼翻譯成更容易理解的代碼時(shí),它們會(huì)有所幫助。
用來(lái)開(kāi)始和結(jié)束函數(shù)體,例如:
CREATE FUNCTION foo() RETURNS integer AS '
....
' LANGUAGE plpgsql;
在一個(gè)單引號(hào)引用的函數(shù)體中的任何位置,引號(hào)必須成對(duì)出現(xiàn)。
用于函數(shù)體內(nèi)的字符串,例如:
a_output := ''Blah'';
SELECT * FROM users WHERE f_name=''foobar'';
在美元引用方法中,你只需要寫(xiě):
a_output := 'Blah';
SELECT * FROM users WHERE f_name='foobar';
這恰好就是PL/pgSQL在兩種情況中會(huì)看到的。
當(dāng)你在函數(shù)內(nèi)的一個(gè)字符串常量中需要一個(gè)單引號(hào)時(shí),例如:
a_output := a_output || '' AND name LIKE ''''foobar'''' AND xyz''
實(shí)際會(huì)被追加到a_output
的值將是: AND name LIKE 'foobar' AND xyz
。
在美元引用方法中,你可以寫(xiě):
a_output := a_output || $$ AND name LIKE 'foobar' AND xyz$$
要小心在這周?chē)娜魏蚊涝枚ń绶恢皇?code class="literal">$$。
當(dāng)在函數(shù)體內(nèi)的一個(gè)字符串中的一個(gè)單引號(hào)與該字符串常量末尾相鄰,例如:
a_output := a_output || '' AND name LIKE ''''foobar''''''
被追加到a_output
的值則將是: AND name LIKE 'foobar'
。
在美元引用方法中,這會(huì)變成:
a_output := a_output || $$ AND name LIKE 'foobar'$$
當(dāng)你想在一個(gè)字符串常量(占 8 個(gè)引號(hào))中有兩個(gè)單引號(hào)時(shí)并且這會(huì)挨著該字符串常量的末尾(另外 2 個(gè))。如果你正在寫(xiě)一個(gè)產(chǎn)生其他函數(shù)的函數(shù)(如例 42.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;
在美元引用方法中,這會(huì)變成:
a_output := a_output || $$ if v_$$ || referrer_keys.kind || $$ like '$$
|| referrer_keys.key_string || $$'
then return '$$ || referrer_keys.referrer_type
|| $$'; end if;$$;
這里我們假定我們只需要把單引號(hào)放在a_output
中,因?yàn)樵谑褂们八鼘⒈辉僖谩?/p>
為了輔助用戶在一些簡(jiǎn)單但常見(jiàn)的問(wèn)題產(chǎn)生危害之前找到它們, PL/pgSQL提供了額外的檢查
。當(dāng)被啟用時(shí), 根據(jù)配置,它們可以在一個(gè)函數(shù)的編譯期間被用來(lái)發(fā)出 WARNING
或者ERROR
。一個(gè)已經(jīng)收到了 WARNING
的函數(shù)可以被繼續(xù)執(zhí)行而不會(huì)產(chǎn)生進(jìn)一步的消息,
因此建議你在一個(gè)單獨(dú)的開(kāi)發(fā)環(huán)境中進(jìn)行測(cè)試。
根據(jù)需要設(shè)置 plpgsql.extra_warnings
或 plpgsql.extra_errors
,適當(dāng)情況下,在開(kāi)發(fā)和/或測(cè)試環(huán)境中可以設(shè)置為 "all"
。
這些附加檢查通過(guò)配置變量啟用, plpgsql.extra_warnings
用于警告,plpgsql.extra_errors
用于錯(cuò)誤。 兩者都可以設(shè)置為逗號(hào)分隔的檢查列表,"none"
或 "all"
。 默認(rèn)值為"none"
。當(dāng)前可用的檢查列表包括:
shadowed_variables
檢查聲明是否遮蓋了以前定義的變量
strict_multi_assignment
某些PL/PgSQL命令允許一次將值分配給多個(gè)變量,例如SELECT INTO
。 通常,目標(biāo)變量的數(shù)量和源變量的數(shù)量應(yīng)匹配,盡管PL/PgSQL將使用NULL
來(lái)處理缺失的值和被忽略的額外變量。 啟用此檢查將導(dǎo)致 PL/PgSQL在目標(biāo)變量數(shù)和源變量數(shù)不同時(shí)引發(fā)
WARNING
或ERROR
。
too_many_rows
Enabling this check will cause PL/PgSQL to check if a given query returns more than one row when an INTO
clause is used. As an INTO
statement will only ever use one
row, having a query return multiple rows is generally either inefficient and/or nondeterministic and therefore is likely an error. 啟用此檢查將導(dǎo)致PL/PgSQL檢查在使用INTO
子句時(shí)給定查詢是否返回多行。 由于INTO
語(yǔ)句只會(huì)使用一行,讓查詢返回多行通常會(huì)效率低下和/或不確定性,因此很可能會(huì)出現(xiàn)錯(cuò)誤。
下面的示例顯示了plpgsql.extra_warnings
設(shè)置為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
設(shè)置為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)
Copyright©2021 w3cschool編程獅|閩ICP備15016281號(hào)-3|閩公網(wǎng)安備35020302033924號(hào)
違法和不良信息舉報(bào)電話:173-0602-2364|舉報(bào)郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號(hào)
聯(lián)系方式:
更多建議: