3
Are PL/SQL stored procedures transactions? When a trigger, procedure or function runs, is it a transaction?
PL / SQL存储过程是否是事务?当触发器,过程或函数运行时,它是一个事务吗?
No. A transaction starts with the first DML encountered and ends when it encounters a COMMIT or ROLLBACK. A transaction can comprise many function and procedure calls and DML statements and trigger code. On the other hand, you can create a procedure that comprises of many transactions by issuing lots of COMMITs.
否。事务从遇到的第一个DML开始,在遇到COMMIT或ROLLBACK时结束。事务可以包含许多函数和过程调用以及DML语句和触发器代码。另一方面,您可以通过发出大量COMMIT来创建包含许多事务的过程。
I usually end my procedures with COMMIT and when an error occurs I use ROLLBACK! Is it wrong?
我通常用COMMIT结束我的程序,当发生错误时我使用ROLLBACK!这是错的吗?
Wrong is a strong word. Let's just say it's not a good practice. Making (packaged) functions and procedures is all about modularization: making reusable pieces of code. When a function/procedure contains ROLLBACK or COMMIT statements, it stops being reusable as it messes up the transaction of the caller. So it's better not to use ROLLBACK or COMMIT in your procedures and leave it to the topmost caller.
错误是一个强有力的词。我们只是说这不是一个好习惯。制作(打包)函数和过程都是关于模块化的:制作可重用的代码片段。当函数/过程包含ROLLBACK或COMMIT语句时,它会停止可重用,因为它会扰乱调用者的事务。因此,最好不要在程序中使用ROLLBACK或COMMIT,并将其留给最顶层的调用者。
You could use SAVEPOINTS throughout your code which makes sure a single function or procedure doesn't leave open parts of a transaction. But for esthetical reasons I prefer to not use SAVEPOINTS. For me, it's just five lines of unnecessary code, because I know my caller function will handle the transaction just nicely.
您可以在整个代码中使用SAVEPOINTS,这样可以确保单个函数或过程不会保留事务的开放部分。但出于美学原因,我宁愿不使用SAVEPOINTS。对我来说,这只是五行不必要的代码,因为我知道我的调用函数会很好地处理事务。
Exception is when you create an autonomous procedure, which is by definition a single transaction and thus needs to end with a COMMIT.
例外情况是您创建一个自治过程,根据定义,它是一个单独的事务,因此需要以COMMIT结束。
UPDATE
Note that a RAISE_APPLICATION_ERROR or a RAISE [exception name] statement will also automatically rollback your PL/SQL block as a single atomic unit. Which is of course a desirable effect as it doesn't leave you with uncommitted changes.
请注意,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.