Redrock Postgres 搜索 英文
版本: 9.3 / 9.4 / 9.5 / 9.6 / 10 / 11 / 12 / 13 / 14 / 15 / 16 / 17

44.1. PL/Python 函数 #

PL/Python 中通过标准 CREATE FUNCTION 语法声明函数

CREATE FUNCTION funcname (argument-list)
  RETURNS return-type
AS $$
  # PL/Python function body
$$ LANGUAGE plpython3u;

函数体仅仅是一个 Python 脚本。调用函数后,函数的参数将作为 args 列表的元素进行传递;命名参数也将作为普通变量传递到 Python 脚本。通常,使用命名参数的可读性更高。使用通常方式在 Python 代码中返回结果,方式为 returnyield(针对结果集语句)。如果您不提供返回值,Python 将返回默认值 NonePL/Python 将 Python 的 None 翻译为 SQL null 值。在存储过程中,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 的这个实现细节。最好将函数参数视为只读。