pgsql.cc 提供对 postgresql.org 官网内容的中文翻译,由 Pigsty 团队维护。
PL/Python 语言模块会自动导入一个名为plpy的 Python 模块。该模块中的函数和常量在 Python 代码中可以通过plpy.这样的形式访问。foo
plpy 模块提供了两个函数: execute 和 prepare。使用 查询字符串和一个可选的限制参数调用 plpy.execute 会执行该查询,并把结果在一个 结果对象中返回。结果对象模拟了列表或字典对象。可以通过行号和 列名访问结果对象。它还有这些附加方法: nrows 返回查询返回的行数, status 是 SPI_execute() 的返回值。结果对象可以被修改。
例如:
rv = plpy.execute("SELECT * FROM my_table", 5)
会从 my_table 中返回最多 5 行。如果 my_table 有一列名为 my_column, 则可以这样访问它:
foo = rv[i]["my_column"]
第二个函数 plpy.prepare 为查询准备执行计划。 若查询中有参数引用,则它以查询字符串和参数类型列表作为参数。例如:
plan = plpy.prepare("SELECT last_name FROM my_users WHERE first_name = $1", [ "text" ])
text 是你要传给 $1 的变量的 类型。准备好语句之后,使用函数 plpy.execute 运行它:
rv = plpy.execute(plan, [ "name" ], 5)
第三个参数是限制,它是可选的。
查询参数和结果行字段会按照第 42.3 节中所述,在 PostgreSQL 与 Python 数据类型之间进行转换。
当你使用 PL/Python 模块准备一个计划时,它会被自动保存。关于这 意味着什么,请参阅 SPI 文档(第 43 章)。为了在函数 调用之间有效利用这一点,需要使用持久存储字典 SD 或 GD 之一(见 第 42.4 节)。例如:
CREATE FUNCTION usesavedplan() RETURNS trigger AS $$
if SD.has_key("plan"):
plan = SD["plan"]
else:
plan = plpy.prepare("SELECT 1")
SD["plan"] = plan
# rest of function
$$ LANGUAGE plpythonu;
访问数据库的函数可能会遇到错误,这会导致它们中止并抛出异常。plpy.execute和plpy.prepare都可能抛出plpy.SPIError某个子类的实例,默认情况下这会终止函数。这个错误可以像其他 Python 异常一样,通过try/except结构来处理。例如:
CREATE FUNCTION try_adding_joe() RETURNS text AS $$
try:
plpy.execute("INSERT INTO users(username) VALUES ('joe')")
except plpy.SPIError:
return "something went wrong"
else:
return "Joe added"
$$ LANGUAGE plpythonu;
所抛出异常的实际类,对应引发错误的具体条件。参见 表 A.1 中列出的可能条件。模块 plpy.spiexceptions 为每种 PostgreSQL 条件定义了一个异常类,类名由条件名派生。例如,division_by_zero 变为 DivisionByZero, unique_violation 变为 UniqueViolation, fdw_error 变为 FdwError,依此类推。所有这些异常类都继承自 SPIError。这样区分之后,更容易处理特定错误,例如:
CREATE FUNCTION insert_fraction(numerator int, denominator int) RETURNS text AS $$
from plpy import spiexceptions
try:
plan = plpy.prepare("INSERT INTO fractions (frac) VALUES ($1 / $2)", ["int", "int"])
plpy.execute(plan, [numerator, denominator])
except spiexceptions.DivisionByZero:
return "denominator cannot equal zero"
except spiexceptions.UniqueViolation:
return "already have that fraction"
except plpy.SPIError, e:
return "other error, SQLSTATE %s" % e.sqlstate
else:
return "fraction inserted"
$$ LANGUAGE plpythonu;
注意,因为 plpy.spiexceptions 模块中的所有异常都继承自 SPIError,所以处理它的 except 子句会捕获任何数据库访问错误。
作为处理不同错误情况的另一种方法,你可以捕获SPIError异常,并在except块中通过查看异常对象的sqlstate属性来判断具体的错误条件。该属性是一个包含“SQLSTATE”错误代码的字符串值。这种方法大体上提供了相同的功能。
译文有误、术语不当或页面显示问题,请到译文仓库 pgsty/pgdoc 报告译文问题。 英文原文本身的问题,请在当前版本的对应页面向上游反馈;上游不再修订已结束维护的版本。