Oracle:立即执行和 ORA-01086 中的保存点
Posted
技术标签:
【中文标题】Oracle:立即执行和 ORA-01086 中的保存点【英文标题】:Oracle: Savepoints within execute immediate and ORA-01086 【发布时间】:2018-04-26 07:58:05 【问题描述】:有人知道,为什么我在以下代码中得到一个ORA-01086: savepoint 'SPX' never established in this session or is invalid?
begin
rollback; --clear all Transactions
execute immediate 'begin
savepoint SPX;
raise no_data_found;
end;';
exception when no_data_found then
rollback to savepoint SPX;
end;
如果我不使用立即执行,它就可以工作:
begin
rollback; --clear all Transactions
begin
savepoint SPX;
raise no_data_found;
end;
exception when no_data_found then
rollback to savepoint SPX;
end;
这是预期的行为还是类似于错误?
我正在使用Oracle Database 12c Enterprise Edition Release 12.1.0.2.0 - 64bit Production
更新: 以下示例也可以使用,它使用动态 SQL 与 Savepoints 相结合:
begin
rollback; --clear all Transactions
execute immediate 'begin
savepoint SPX;
end;';
rollback to savepoint SPX;
end;
【问题讨论】:
【参考方案1】:问题是在异常传播到外部块之前,会发生隐式 ROLLBACK,这会删除块创建的保存点。
这是一个重现问题但使用静态 SQL 的示例:
begin
rollback; --clear all Transactions
savepoint SPX;
rollback;
raise no_data_found;
exception when no_data_found then
rollback to savepoint SPX;
end;
ORA-01086: savepoint 'SPX' never established in this session or is invalid ORA-06512: at line 7
不幸的是,您被这种行为所困扰;动态 SQL 必须在其自己的上下文中运行,如果它引发异常(并且不处理它),则会发出 ROLLBACK。
您需要在运行动态 SQL 之前创建保存点;或者,您可以抑制 ORA-01086 错误:
begin
rollback; --clear all Transactions
execute immediate 'begin
savepoint SPX;
raise no_data_found;
end;';
exception when no_data_found then
begin
rollback to savepoint SPX;
exception when others then
if sqlcode != -1086 /*savepoint never established*/ then
raise;
end if;
end;
end;
【讨论】:
【参考方案2】:在Oracle Doc on the SAVEPOINT statement 中说:
SQL SAVEPOINT 语句可以作为静态 SQL 嵌入到 PL/SQL 中。
所以我认为这可以被认为是一种预期的行为。
【讨论】:
我用一个使用动态 SQL 和保存点的示例更新了我的问题,没有例外。 好主意!似乎在您的第一个示例中,除了引发 EXECUTE 作为一个块失败,破坏了保存点。 SAVEPOINT 在 PL/SQL 中有效这一事实与这个问题无关。 @JeffreyKemp:这里的关键字是 STATIC。最初的问题是静态 SQL 和动态 SQL 之间是否存在差异。以上是关于Oracle:立即执行和 ORA-01086 中的保存点的主要内容,如果未能解决你的问题,请参考以下文章