如果Rollback语句调用而未指定保存点,该怎么办?

时间:2017-06-09 09:15:02

标签: sql oracle plsql

我们可以在Oracle中创建保存点,然后通过调用ROLLBACK TO SAVEPOINT <savepoint_name>我们可以回滚到特定的保存点。

UPDATE employees 
    SET salary = 7000 
    WHERE last_name = 'Banda';
SAVEPOINT banda_sal;

UPDATE employees 
    SET salary = 12000 
    WHERE last_name = 'Greene';
SAVEPOINT greene_sal;

SELECT SUM(salary) FROM employees;

ROLLBACK; --> the rollback without the savepoint

UPDATE employees 
    SET salary = 11000 
    WHERE last_name = 'Greene';

COMMIT;  

有人可以解释上面的代码是如何工作的吗?

这可以被视为一个愚蠢的问题。但是,在某些情况下,很难确定在复杂的PL SQL程序中执行ROLLBACK语句的位置(如果您只需对现有代码进行修改)。

2 个答案:

答案 0 :(得分:3)

关于这个评论:

  

但是在某些情况下,很难确定在复杂的PL SQL程序中执行ROLLBACK语句的位置(如果您只需对现有代码进行修改)。

如果您正在运行Oracle Database 12c第2版实例(现在可从OTN,Github和Docker下载,或多个云服务),您可以利用PL / Scope查找代码中提交的所有位置并执行回滚(PL / Scope首先在11.1中添加,但在12.2中添加了对SQL语句的分析):

您必须首先启用范围数据的收集:

ALTER SESSION SET plscope_settings='identifiers:all, statements:all'

然后在编译程序单元时,将信息放入ALL_IDENTIFIERS(PL / SQL语句)和ALL_STATEMENTS(SQL语句,12.2中的新语句)。

完成后,以下查询将找到所有提交和回滚:

SELECT st.owner,
       st.object_name,
       st.object_type,
       st.line,
       src.text
  FROM all_statements st, all_source src
 WHERE     st.TYPE = 'COMMIT'
       AND st.object_name = src.name
       AND st.owner = src.owner
       AND st.line = src.line
ORDER BY st.owner,
         st.object_name,
         st.object_type   
/

SELECT st.owner,
       st.object_name,
       st.object_type,
       st.line,
       src.text
  FROM all_statements st, all_source src
 WHERE     st.TYPE = 'ROLLBACK'
       AND st.object_name = src.name
       AND st.owner = src.owner
       AND st.line = src.line
ORDER BY st.owner,
         st.object_name,
         st.object_type    
/

您可以找到有关PL / Scope here的更多信息和示例。

答案 1 :(得分:2)

如果你不使用&#34;保存点到&#34; rollback会回滚到点(在您的示例中为first update,因为您的交易从first update开始),rollback之后如果您使用的是DML third update (在您的示例中为third update)最后&#34;提交&#34;将仅提交事务的最后一部分(在最后一次回滚部分之后,--- start transactions UPDATE employees SET salary = 7000 WHERE last_name = 'Banda'; SAVEPOINT banda_sal; UPDATE employees SET salary = 12000 WHERE last_name = 'Greene'; SAVEPOINT greene_sal; SELECT SUM(salary) FROM employees; ROLLBACK; -- roolback to first DML("start transactions" part,because there is no any savepoint to) UPDATE employees SET salary = 11000 WHERE last_name = 'Greene'; COMMIT; -- commit only last update

a_row + b_row