W3Cschool
恭喜您成為首批注冊用戶
獲得88經(jīng)驗(yàn)值獎(jiǎng)勵(lì)
要用 PL/Perl 語言創(chuàng)建一個(gè)函數(shù),可使用標(biāo)準(zhǔn)的 CREATE FUNCTION語法:
CREATE FUNCTION funcname
(argument-types
)
RETURNS return-type
-- function attributes can go here
AS $$
# PL/Perl function body goes here
$$ LANGUAGE plperl;
函數(shù)的主體就是普通的 Perl 代碼。事實(shí)上,PL/Perl 的粘合代碼會把它 包裹在一個(gè) Perl 子程序中。一個(gè) PL/Perl 函數(shù)會在一種標(biāo)量上下文中 被調(diào)用,因此它無法返回列表。如下文所述,可以通過返回引用來返回 非標(biāo)量值(數(shù)組、記錄和集合)。
在一個(gè)PL/Perl過程中,任何從Perl代碼返回的值都會被忽略。
PL/Perl 也支持用DO語句調(diào)用的匿名代碼塊:
DO $$
# PL/Perl 代碼
$$ LANGUAGE plperl;
一個(gè)匿名代碼塊沒有參數(shù),并且它返回的任何值都會被拋棄。否則 其行為就像一個(gè)函數(shù)。
在 Perl 中使用命名嵌套子程序是有危險(xiǎn)的,特別是當(dāng)它們在作用域內(nèi) 引用局部變量時(shí)。因?yàn)?PL/Perl 函數(shù)被包裝成一個(gè)子程序,任何放在 其中的命名子程序都會被嵌套??傊?,創(chuàng)建通過 coderef 調(diào)用的匿名 子程序要安全得多。更多信息可見 perldiag手冊頁 中的Variable "%s" will not stay shared
以及
Variable "%s" is not available
,或者在互聯(lián)網(wǎng)上 搜索“perl nested named subroutine”。
CREATE FUNCTION
命令的語法要求函數(shù) 體被寫作一個(gè)字符串常量。通常對字符串常量使用美元引用(見 第 4.1.2.4 節(jié))最方便。如果選擇使用 轉(zhuǎn)義字符串語法E''
,必須雙寫任何在函數(shù)體中使用的單引號
('
)和反斜線(\
)(見 第 4.1.2.1 節(jié))。
參數(shù)和結(jié)果的處理和在任何其他 Perl 子程序中一樣:參數(shù)被傳遞到 @_
中,并且結(jié)果值用return
返回或者把函數(shù)中計(jì)算的最后一個(gè)表達(dá)式作為結(jié)果值。
例如,一個(gè)返回兩個(gè)整數(shù)值中較大值的函數(shù)可以定義為:
CREATE FUNCTION perl_max (integer, integer) RETURNS integer AS $$
if ($_[0] > $_[1]) { return $_[0]; }
return $_[1];
$$ LANGUAGE plperl;
參數(shù)將被從數(shù)據(jù)庫的編碼轉(zhuǎn)換到 PL/Perl 中使用的 UTF-8,返回時(shí)再從 UTF-8 轉(zhuǎn)回到數(shù)據(jù)庫編碼。
如果一個(gè) SQL 空值
被傳給一個(gè)函數(shù),在 Perl 中該參數(shù)值將呈現(xiàn)為“undefined”。上述函數(shù)定義對于 空輸入的行為不太好(實(shí)際上,它會把它們當(dāng)作零)。我們可以為函數(shù) 定義增加STRICT
讓PostgreSQL
干得更合理:如果空值被傳入,函數(shù)將根本不會被調(diào)用,而只是自動(dòng) 返回一個(gè)空結(jié)果。另外一種方式,我們可以在函數(shù)體中檢查未定義的
輸入。例如,假設(shè)我們想讓帶有一個(gè)空參數(shù)或者一個(gè)非空參數(shù)的 perl_max
返回非空參數(shù)而不是空值:
CREATE FUNCTION perl_max (integer, integer) RETURNS integer AS $$
my ($x, $y) = @_;
if (not defined $x) {
return undef if not defined $y;
return $y;
}
return $x if not defined $y;
return $x if $x > $y;
return $y;
$$ LANGUAGE plperl;
如上所述,要從一個(gè) PL/Perl 函數(shù)返回一個(gè) SQL 空值,就返回一個(gè)未定義值。 不管函數(shù)是嚴(yán)格的還是非嚴(yán)格的都可以這樣做。
一個(gè)非引用的函數(shù)參數(shù)中的任何東西都是一個(gè)串,是相關(guān)數(shù)據(jù)類型的標(biāo)準(zhǔn) PostgreSQL外部文本表達(dá)。在普通 數(shù)字或文本類型的情況下,Perl 將會做正確的事情并且程序員通常不需要 操心。不過,在其他情況下將需要被轉(zhuǎn)換成在 Perl 中更可用的形式。例如, decode_bytea
函數(shù)可以被用來把類型 bytea
的參數(shù)轉(zhuǎn)換成未轉(zhuǎn)義的二進(jìn)制形式。
類似地,回傳給PostgreSQL的值必須 是外部文本表達(dá)格式。例如,encode_bytea
函數(shù)可以被用來轉(zhuǎn)義二進(jìn)制數(shù)據(jù)得到類型bytea
的返回值。
一種特別重要的情況是布爾值。如前所述,bool
值的默認(rèn)行為是它們作為文本傳遞給 Perl, 因此要么't'
要么'f'
。 這是有問題的,因?yàn)?Perl 不會將'f'
視為假! 可以通過使用“transform”來改善問題(參見
CREATE TRANSFORM
)。 bool_plperl
擴(kuò)展提供了合適的轉(zhuǎn)換。要使用它,請安裝擴(kuò)展:
CREATE EXTENSION bool_plperl; -- or bool_plperlu for PL/PerlU
然后將TRANSFORM
函數(shù)屬性用于接受或返回bool
的 PL/Perl 函數(shù),例如:
CREATE FUNCTION perl_and(bool, bool) RETURNS bool
TRANSFORM FOR TYPE bool
AS $$
my ($a, $b) = @_;
return $a && $b;
$$ LANGUAGE plperl;
當(dāng)應(yīng)用這個(gè)轉(zhuǎn)換時(shí),bool
參數(shù)將被 Perl 視為1
或空,因此正確或錯(cuò)誤。 如果函數(shù)結(jié)果是bool
類型,它會根據(jù) Perl 是否將返回值評估為真來判斷為真或假。 函數(shù)內(nèi)部執(zhí)行的 SPI 查詢的布爾查詢參數(shù)和結(jié)果也執(zhí)行類似的轉(zhuǎn)換(第 44.3.1 節(jié))。
Perl 可以把PostgreSQL數(shù)組返回為對 Perl 數(shù)組的引用。這里有一個(gè)例子:
CREATE OR REPLACE function returns_array()
RETURNS text[][] AS $$
return [['a"b','c,d'],['e\\f','g']];
$$ LANGUAGE plperl;
select returns_array();
Perl 把PostgreSQL數(shù)組作為被 bless 過的 PostgreSQL::InServer::ARRAY
對象傳遞。這個(gè)對象可以被當(dāng)作 一個(gè)數(shù)組引用或者一個(gè)串,允許為了向后兼容性與為 9.1 以下版本的 PostgreSQL編寫的 Perl 代碼一起運(yùn)行。 例如:
CREATE OR REPLACE FUNCTION concat_array_elements(text[]) RETURNS TEXT AS $$
my $arg = shift;
my $result = "";
return undef if (!defined $arg);
# as an array reference
for (@$arg) {
$result .= $_;
}
# also works as a string
$result .= $arg;
return $result;
$$ LANGUAGE plperl;
SELECT concat_array_elements(ARRAY['PL','/','Perl']);
多維數(shù)組被以一種對每一個(gè) Perl 程序員都公認(rèn)的方法表示為對較低維引用數(shù)組 的引用。
組合類型參數(shù)被作為哈希的引用傳遞給函數(shù)。哈希的鍵是組合類型的 屬性名。這里是一個(gè)例子:
CREATE TABLE employee (
name text,
basesalary integer,
bonus integer
);
CREATE FUNCTION empcomp(employee) RETURNS integer AS $$
my ($emp) = @_;
return $emp->{basesalary} + $emp->{bonus};
$$ LANGUAGE plperl;
SELECT name, empcomp(employee.*) FROM employee;
PL/Perl 函數(shù)可以使用相同的方法返回組合類型:返回具有所要求屬性的 哈希的引用。例如:
CREATE TYPE testrowperl AS (f1 integer, f2 text, f3 text);
CREATE OR REPLACE FUNCTION perl_row() RETURNS testrowperl AS $$
return {f2 => 'hello', f1 => 1, f3 => 'world'};
$$ LANGUAGE plperl;
SELECT * FROM perl_row();
任何所要求結(jié)果數(shù)據(jù)類型中不存在于哈希中的列將被返回為空值。
類似的,過程的輸出參數(shù)也可以被返回為哈希引用:
CREATE PROCEDURE perl_triple(INOUT a integer, INOUT b integer) AS $$
my ($a, $b) = @_;
return {a => $a * 3, b => $b * 3};
$$ LANGUAGE plperl;
CALL perl_triple(5, 10);
PL/Perl 函數(shù)也能返回標(biāo)量或者組合類型集合。為了加速啟動(dòng)并且避免在 內(nèi)存中讓整個(gè)結(jié)果集排隊(duì)等候,我們通常希望能一次返回一行。可以按 下文所說的用return_next
來這樣做。注意在 最后一次return_next
后,必須放上 return
或者return
undef
(后者更好)。
CREATE OR REPLACE FUNCTION perl_set_int(int)
RETURNS SETOF INTEGER AS $$
foreach (0..$_[0]) {
return_next($_);
}
return undef;
$$ LANGUAGE plperl;
SELECT * FROM perl_set_int(5);
CREATE OR REPLACE FUNCTION perl_set()
RETURNS SETOF testrowperl AS $$
return_next({ f1 => 1, f2 => 'Hello', f3 => 'World' });
return_next({ f1 => 2, f2 => 'Hello', f3 => 'PostgreSQL' });
return_next({ f1 => 3, f2 => 'Hello', f3 => 'PL/Perl' });
return undef;
$$ LANGUAGE plperl;
對于小結(jié)果集,可以返回到一個(gè)數(shù)組的引用,該數(shù)組分別包含用于 簡單類型、數(shù)組類型和組合類型的標(biāo)量、數(shù)組引用或者哈希引用。 這里有一些簡單的例子把整個(gè)結(jié)果集作為數(shù)組引用返回:
CREATE OR REPLACE FUNCTION perl_set_int(int) RETURNS SETOF INTEGER AS $$
return [0..$_[0]];
$$ LANGUAGE plperl;
SELECT * FROM perl_set_int(5);
CREATE OR REPLACE FUNCTION perl_set() RETURNS SETOF testrowperl AS $$
return [
{ f1 => 1, f2 => 'Hello', f3 => 'World' },
{ f1 => 2, f2 => 'Hello', f3 => 'PostgreSQL' },
{ f1 => 3, f2 => 'Hello', f3 => 'PL/Perl' }
];
$$ LANGUAGE plperl;
SELECT * FROM perl_set();
如果你想要對你的代碼使用strict
編譯指示,有幾種選項(xiàng)可用。 對于臨時(shí)的全局使用,你可以SET
plperl.use_strict
為真。這將影響后續(xù) PL/Perl函數(shù)的編譯,但是對當(dāng)前會話中已經(jīng)編譯過的 函數(shù)沒有影響。對于持久的全局使用,可以在 postgresql.conf
文件中設(shè)置
plperl.use_strict
為真。
對于在特定函數(shù)中的持久使用,可以簡單地把
use strict;
放在函數(shù)體的頂層。
如果 Perl 版本是 5.10.0 或者更高,也可以使用
feature
編譯指示。
Copyright©2021 w3cschool編程獅|閩ICP備15016281號-3|閩公網(wǎng)安備35020302033924號
違法和不良信息舉報(bào)電話:173-0602-2364|舉報(bào)郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號
聯(lián)系方式:
更多建議: