46.1. PL/Python 函数 #
PL/Python 中的函数通过标准的 CREATE FUNCTION 语法声明:
CREATE FUNCTIONfuncname(argument-list) RETURNSreturn-typeAS $$ # PL/Python 函数体 $$ LANGUAGE plpython3u;
函数体只是一个 Python 脚本。调用函数时,其参数会作为列表 args 的元素传入;命名参数还会作为普通变量传给 Python 脚本。使用命名参数通常可读性更好。结果通常通过 return 或 yield(在返回结果集的情况下)从 Python 代码返回。如果不提供返回值,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() # 错误 return x $$ LANGUAGE plpython3u;
因为对 x 赋值会使 x 在整个代码块中都成为局部变量,因此赋值语句右侧的 x 指向的是尚未赋值的局部变量 x,而不是 PL/Python 函数参数。使用 global 语句后,这样写就能工作:
CREATE FUNCTION pystrip(x text) RETURNS text AS $$ global x x = x.strip() # 现在可以正常工作 return x $$ LANGUAGE plpython3u;
但是,建议不要依赖 PL/Python 的这一实现细节。最好将函数参数视为只读。
报告文档问题
阅读 上游文档. 通过 PostgreSQL 文档反馈表单.