PL/Python 中的函数通过标准的CREATE FUNCTION语法声明:
CREATE FUNCTIONfuncname(argument-list) RETURNSreturn-typeAS $$ # PL/Python function body $$ LANGUAGE plpythonu;
函数体就是一段 Python 脚本。调用函数时,参数作为列表 args 的元素传入;命名参数还会作为普通变量传给 Python 脚本。使用命名参数通常更易读。Python 代码按通常方式用 return 或 yield(返回结果集时)返回结果。如果没有提供返回值,Python 默认返回 None。PL/Python 会将 Python 的 None 转换为 SQL 空值。
例如,一个返回两个整数中较大值的函数可以定义为:
CREATE FUNCTION pymax (a integer, b integer)
RETURNS integer
AS $$
if a > b:
return a
return b
$$ LANGUAGE plpythonu;
函数定义体中给出的 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 plpythonu;
因为对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 plpythonu;
但是,建议不要依赖 PL/Python 的这一实现细节。最好将函数参数视为只读。