【发布时间】:2017-02-20 17:22:16
【问题描述】:
我正在 PostgreSQL 数据库上创建过程。我读到的是不可能在这些程序中使用回滚。
为什么?
可以使用commit吗?
我猜这与 ACID 属性有关,但是如果我们在一个过程中有两个插入操作怎么办。如果第二个失败,第二个会回滚吗?
谢谢。
【问题讨论】:
-
一方面,因为Postgres没有过程,只有函数。
标签: postgresql stored-procedures
我正在 PostgreSQL 数据库上创建过程。我读到的是不可能在这些程序中使用回滚。
为什么?
可以使用commit吗?
我猜这与 ACID 属性有关,但是如果我们在一个过程中有两个插入操作怎么办。如果第二个失败,第二个会回滚吗?
谢谢。
【问题讨论】:
标签: postgresql stored-procedures
Postgres' overview 通过解释它们的功能与传统存储过程有何不同来给出提示:
使用 PL/pgSQL 创建的函数可以在任何可以使用内置函数的地方使用。例如,可以创建复杂的条件计算函数,然后使用它们来定义运算符或在索引表达式中使用它们。
这使得在每个可能的情况下支持函数内的事务变得很尴尬。来自the docs:
函数和触发过程总是在由外部查询建立的事务中执行...但是,包含 EXCEPTION 子句的块有效地形成了可以回滚而不影响外部事务的子事务。
如果您要在一个函数中有两个 INSERT,第一个可以包装在 EXCEPTION 块中以捕获任何错误并决定是否应该执行第二个。
【讨论】:
你是对的。您不能从过程中回滚在过程之前启动的事务。此外,也不能在过程中创建事务。你会收到这个错误:
ERROR: cannot begin/end transactions in PL/pgSQL
SQL state: 0A000
Hint: Use a BEGIN block with an EXCEPTION clause instead.
正如这个错误所指出的,正如 Matt 所提到的,您可以使用异常块来实质上执行回滚。来自help:
当错误被 EXCEPTION 子句捕获时,PL/pgSQL 函数的局部变量将保持与错误发生时的状态相同,但对块内持久数据库状态的所有更改都会回滚。
或者,您可以在事务中调用该过程,并在必要时回滚。
【讨论】: