PL / SQL存储过程是否是事务?

时间:2014-09-19 11:19:58

标签: sql database oracle stored-procedures transactions

PL / SQL存储过程是否是事务? 当触发器,过程或函数运行时,它是一个事务吗? 我通常用COMMIT结束我的程序,当发生错误时我使用ROLLBACK!这是错的吗?

我没有询问START TRANSACTION程序,但我想知道它们是否是交易。

谢谢。

3 个答案:

答案 0 :(得分:3)

Are PL/SQL stored procedures transactions? When a trigger, procedure or function runs, is it a transaction?

没有。事务从遇到的第一个DML开始,在遇到COMMIT或ROLLBACK时结束。事务可以包含许多函数和过程调用以及DML语句和触发器代码。另一方面,您可以通过发出大量COMMIT来创建包含许多事务的过程。

I usually end my procedures with COMMIT and when an error occurs I use ROLLBACK! Is it wrong?

错误是一个强有力的词。我们只是说这不是一个好习惯。制作(打包)函数和过程都是关于模块化的:制作可重用的代码片段。当函数/过程包含ROLLBACK或COMMIT语句时,它会停止重用,因为它会扰乱调用者的事务。因此,最好不要在程序中使用ROLLBACK或COMMIT,并将其留给最顶层的调用者。

您可以在整个代码中使用SAVEPOINTS,这样可以确保单个函数或过程不会保留事务的开放部分。但出于美学原因,我宁愿不使用SAVEPOINTS。对我来说,它只有五行不必要的代码,因为我知道我的调用函数会很好地处理事务。

异常是在创建自治过程时,根据定义,该过程是单个事务,因此需要以COMMIT结束。

<强>更新

请注意,RAISE_APPLICATION_ERROR或RAISE [exception name]语句也会自动将PL / SQL块作为单个原子单元回滚。这当然是一种理想的效果,因为它不会给你带来未经提及的变化。

SQL> create table mytable (id int)
  2  /

Table created.

SQL> create procedure p
  2  as
  3  begin
  4    insert into mytable values (2);
  5    raise_application_error(-20000,'My exception');
  6  end;
  7  /

Procedure created.

SQL> select *
  2    from mytable
  3  /

no rows selected

SQL> insert into mytable values (1)
  2  /

1 row created.

SQL> exec p
BEGIN p; END;

*
ERROR at line 1:
ORA-20000: My exception
ORA-06512: in "X.P", regel 5
ORA-06512: in regel 1


SQL> select *
  2    from mytable
  3  /

        ID
----------
         1

1 row selected.

答案 1 :(得分:0)

PL / SQL是修改,而不是事务。事务是修改和只读操作的列表。如果你有

update
insert
pl/sql
update
rollback

即使执行了pl / sql,PL / SQL也不会对数据库进行更改。

答案 2 :(得分:0)

当然,这不是交易,而是修改。而且您不需要每次都指定Commit来保存您的交易。 例如,在Oracle中,所有单独的DML语句都是原子的(即它们要么完全成功,要么在第一次失败时回滚任何中间更改)(除非你使用EXCEPTIONS INTO选项,我不会在这里讨论)。 考虑一个上面的例子: 如果您希望将一组语句视为单个原子事务,则可以执行以下操作:

BEGIN
  SAVEPOINT start_tran;
  INSERT INTO .... ; -- first DML
  UPDATE .... ; -- second DML
  BEGIN ... END; -- some other work
  UPDATE .... ; -- final DML
EXCEPTION
  WHEN OTHERS THEN
    ROLLBACK TO start_tran;
    RAISE;
END;

这样,任何异常都会导致回滚此块中的语句,但不会回滚在此块之前运行的任何语句。

请注意,我没有包含COMMIT - 通常我更喜欢调用进程来发出提交。