PL/Python 中的函数通过标准的 CREATE FUNCTION 语法声明:
CREATE FUNCTIONfuncname(argument-list) RETURNSreturn-typeAS $$ # PL/Python function body $$ LANGUAGE plpython3u;
函数体就是一个 Python 脚本。当函数被调用时,其参数作为列表
args 的元素传入;命名参数也会作为普通变量传给
Python 脚本。使用命名参数通常可读性更好。结果按 Python 的常规方式
返回,使用 return 或
yield(对于结果集语句)。如果不提供返回值,
Python 会返回默认的 None。
PL/Python 把 Python 的
None 翻译为 SQL 空值。在过程中,Python 代码的
结果必须是 None(通常通过在过程结尾不写
return 语句或使用不带参数的
return 语句来实现);否则会抛出错误。
例如,一个返回两个整数中较大者的函数可以这样定义:
CREATE FUNCTION pymax (a integer, b integer)
RETURNS integer
AS $$
if a > b:
return a
return b
$$ LANGUAGE plpython3u;
作为函数定义体给出的 Python 代码会被转换为一个 Python 函数。例如, 上面会得到:
def __plpython_procedure_pymax_23456():
if a > b:
return a
return b
这里假定 23456 是 PostgreSQL 分配给该 函数的 OID。
参数被设置为全局变量。由于 Python 的作用域规则,这带来一个微妙的 后果:除非把变量重新声明为全局的,否则不能在函数内部把参数变量 重新赋值为一个涉及该变量名本身的表达式的值。例如,下面这样是 行不通的:
CREATE FUNCTION pystrip(x text) RETURNS text AS $$ x = x.strip() # error return x $$ LANGUAGE plpython3u;
因为对 x 赋值会使 x 成为整个
块的局部变量,于是赋值右侧的 x 引用的是尚未赋值
的局部变量 x,而不是 PL/Python 函数参数。
使用 global 语句可以让它工作:
CREATE FUNCTION pystrip(x text) RETURNS text AS $$ global x x = x.strip() # ok now return x $$ LANGUAGE plpython3u;
但建议不要依赖 PL/Python 的这个实现细节。最好把函数参数当作 只读的。