Oracle存储过程中的事务是如何处理的?通常情况下。整个过程是作为一个事务整体被提交或回滚的,这属于数据库的基本知识,这里简单说明:
1通常情况
通常情况下,oralce将整个存储过程作为一个事务整体,整个过程内的事务,要么都提交,要么都回滚。
如下例所示:
例1
- SQL*Plus: Release 11.2.0.1.0 Production on 星期三 1月 4 13:24:22 2012
- Copyright (c) 1982, 2010, Oracle. All rights reserved.
- 请输入用户名: SYSTEM
- 输入口令:
- 连接到:
- Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - Production
- With the Partitioning, OLAP, Data Mining and Real Application Testing options
- SQL> CREATE TABLE T1 (C INT,D INT NOT NULL);
- 表已创建。
- SQL> create or replace procedure pt1 is begin
- 2 insert into t1 values(1,1);
- 3 INSERT INTO T1 VALUES(2,NULL);
- 4 end;
- 5 /
- 过程已创建。
- SQL> CALL PT1();
- CALL PT1()
- *
- 第 1 行出现错误:
- ORA-01400: 无法将 NULL 插入 ("SYSTEM"."T1"."D")
- ORA-06512: 在 "SYSTEM.PT1", line 3
- SQL> SELECT * FROM T1;
- 未选定行
在这个例子中,我们构造了D列不允许为空的表,并故意在过程中执行一个违反约束的插入语句,造成过程调用的回滚操作,最终通过查询表T1,我们发现执行过程的时候,整个过程内的2条INSERT语句都被回滚了。这证明了在通常情况下,存储过程是作为一个事务整体的。
另一方面需要说明的是,在非自动提交的情况下,存储过程除非内部显式的执行了commit操作,否则即便整个过程执行成功,当前事务也是未提交的,这是存储过程的另一个特点:存储过程并不会自动提交。 例子如下:
例2
- SQL> create or replace procedure pt1 is begin
- 2 insert into t1 values(1,1);
- 3 -- INSERT INTO T1 VALUES(2,NULL);
- 4 end;
- 5 /
- 过程已创建。
- SQL> select * from t1;
- 未选定行
- SQL> call pt1();
- 调用完成。
- SQL> select * from t1;
- C D
- ---------- ----------
- 1 1
- SQL> commit; --在这里显式提交
- 提交完成。
- SQL> select * from t1; --提交后能够看到过程插入的记录
- C D
- ---------- ----------
- 1 1
- SQL> call pt1();
- 调用完成。
- SQL> rollback; --在这里显式回滚
- 回退已完成。
- SQL> select * from t1; --发现回滚导致第二次执行存储过程的操作未生效
- C D
- ---------- ----------
- 1 1
- SQL>
但是如果过程内部使用了commit命令或rollback命令,则存储过程就能够自行控制整个事务的结束时机,而不受整个会话的影响 。例如:
例3
- SQL> drop table t1;
- 表已删除。
- SQL> create table t1(c int,d int);
- 表已创建。
- SQL> create or replace procedure pt1 is begin
- 2 insert into t1 values(1,1);
- 3 savepoint pt1;
- 4 insert into t1 values(2,2);
- 5 savepoint pt2;
- 6 commit;
- 7 end;
- 8 /
- 过程已创建。
- SQL> truncate table t1;
- 表已截断。
- SQL> call pt1();
- 调用完成。
- SQL> select * from t1;
- C D
- ---------- ----------
- 1 1
- 2 2
- SQL> rollback;-- 此时即使在过程外执行ROLLBACK,由于过程内已经COMMIT,因此这个ROLLBACK的作用范围将不会影响到过程内部。
- 回退已完成。
- SQL> select * from t1;
- C D
- ---------- ----------
- 1 1
- 2 2
所以总结一下,我们可以在存储过程内执行COMMIT或ROLLBACK,使过程能够自行结束事务。但如果存储过程使用了异常处理呢?这个规律就不是那么显而易见了。
2 异常处理对事务的影响
异常处理对存储过程的事务管理有什么影响?我们看下面的例子,并先来猜一猜。
例4
- --首先创建表
- CREATE TABLE T1(C INT ,D INT NOT NULL);
- --其次创建过程,其中设置了2个保存点,并包含1个异常处理器--异常处理方式很简单,直接将事务回滚到保存点PT1
- --异常处理完成后,显式执行一个commit命令。
- create or replace procedure pt1 is begin
- insert into t1 values(1,1);
- SAVEPOINT PT1;
- INSERT INTO T1 VALUES(2,2);
- SAVEPOINT PT2;
- EXCEPTION
- WHEN OTHERS THEN
- ROLLBACK TO SAVEPOINT PT1;
-
- COMMIT;
- end;
- CALL PT1();
- SELECT * FROM T1; --猜一猜1:请猜猜这里的执行结果将看到什么?
- ROLLBACK;
- SELECT * FROM T1;-- 猜一猜2:请再猜猜这里又将看到什么结果?
题目出来了,请分析一下猜一猜1和猜一猜2的结果吧。
猜一猜1:这一题应该是比较简单的,我们将看到查询结果包含2条记录,正是存储过程中的2个insert语句插入的结果。
猜一猜2:由于存储过程内显式的执行了commit。因此即使再外边再执行rollback, insert 的记录也不会被回滚(类似例3),因此猜一猜2这里仍将看到与猜一猜1一样的结果。
相信不少同学将会得到如上结论。
那么果真如此吗,我们来看看实际结果:
- SQL> truncate table t1;
- 表被截断。
- SQL> create or replace procedure pt1 is begin
- 2 insert into t1 values(1,1);
- 3 SAVEPOINT PT1;
- 4 INSERT INTO T1 VALUES(2,2);
- 5 SAVEPOINT PT2;
- 6 EXCEPTION
- 7 WHEN OTHERS THEN
- 8 ROLLBACK TO SAVEPOINT PT1;
- 9
- 10 COMMIT;
- 11 end;
- 12 /
- 过程已创建。
- SQL> call pt1();
- 调用完成。
- SQL> select * from t1;
- C D
- ---------- ----------
- 1 1
- 2 2
- SQL> rollback;
- 回退已完成。
- SQL> select * from t1;--我们看到了什么?2条记录被回滚掉了!
- 未选定行
很奇怪吧,一旦加入了异常处理,过程内部处于异常处理器之后的COMMIT命令就失效了!只有当commit处于异常处理器之前的时候才不失效(这一点同学们可以自己做实验)。
事实上,说这个commit失效也不完全,它仅仅是在不产生异常触发器的情况下才失效,当触发了异常后,这个commit就会被执行到 ,如下:
- SQL> truncate table t1;
- 表被截断。
- SQL> create or replace procedure pt1 is begin
- 2 insert into t1 values(1,1);
- 3 SAVEPOINT PT1;
- 4 INSERT INTO T1 VALUES(2,null);
- 5 SAVEPOINT PT2;
- 6 EXCEPTION
- 7 WHEN OTHERS THEN
- 8 ROLLBACK TO SAVEPOINT PT1;
- 9
- 10 COMMIT;
- 11 end;
- 12 /
- 过程已创建。
- SQL> call pt1();
- 调用完成。
- SQL> select * from t1;
- C D
- ---------- ----------
- 1 1
- SQL> rollback;
- 回退已完成。
- SQL> select * from t1;
- C D
- ---------- ----------
- 1 1
没想到Oracle的异常处理会对过程内的事务提交产生这种影响?以后写这类存储过程的同学要注意了:
CREATE OR REPLACE PROCEDURE PTST IS
BEGIN
INSERT ……;
PTST2();
PTST3();
EXCEPTION
WHEN …..THEN….
COMMIT;
END;
为了保证子过程的事务都能够完整提交,所以在主过程里面加了commit,千万要注意commit的位置,不能放在exception之后,数据库的存储过程异常处理可不是java那种try{} catch{} finally{}式的异常处理器哦。
其实从语法上讲,异常处理器应该是一个过程的最后一个组成部分,我们不应该再异常处理器之后再写别的命令。即使写了,Oracle也会报错的,如:
- SQL> create or replace procedure pt1 is begin
- 2 insert into t1 values(1,1);
- 3 SAVEPOINT PT1;
- 4 INSERT INTO T1 VALUES(2,2);
- 5 SAVEPOINT PT2;
- 6 EXCEPTION
- 7 WHEN OTHERS THEN
- 8 ROLLBACK TO SAVEPOINT PT1;
- 9 --commit;
- 10 insert into t1 values(3,3)
- 11 end;
- 12 /
- 警告: 创建的过程带有编译错误。
但是对于commit命令,看来Oracle是比较宽容的了。
来源:http://www.itpub.net/thread-1563051-1-1.html
pl/sql异常学习笔记
http://www.blogjava.net/pdw2009/archive/2006/09/19/70595.html
相关推荐
Oracle 存储过程异常处理 Oracle 存储过程异常处理是指在 Oracle 数据库中使用存储过程时出现的异常情况的处理方法。异常处理是指在程序执行过程中出现错误或异常时,采取相应的处理措施,以确保程序的可靠性和...
- `cx_Oracle` 是 Python 开发者用来访问 Oracle 数据库的接口,它允许 Python 程序直接与 Oracle 数据库进行通信,执行 SQL 查询,处理事务等。 - 这个模块支持 Python 2.x 和 3.x 版本,并且兼容 Oracle 的多种...
cx_Oracle还支持更高级的功能,如参数绑定、存储过程调用、事务控制、异常处理等。例如,你可以使用%s占位符来绑定变量,防止SQL注入攻击: ```python query = 'SELECT * FROM table_name WHERE column = %s' ...
例如,它支持绑定变量、游标操作、事务控制、异常处理等特性,极大地简化了开发过程。 在使用cx_Oracle之前,你需要确保已经在系统中安装了Oracle客户端或者Oracle Instant Client,因为cx_Oracle需要这些组件来...
Java-Oracle存储过程是数据库中一种重要...通过上述知识点的介绍,可以看出Java-Oracle存储过程在处理复杂业务逻辑和数据库操作时的强大优势,尽管存在移植性方面的不足,但合理的应用可以大幅提升程序的性能和安全性。
`CallableStatement`用于调用存储过程。 5. **事务管理**: JDBC提供`Connection`对象上的`setAutoCommit()`和`commit()`/`rollback()`方法,用于手动控制事务边界。 6. **结果集处理**: `ResultSet`接口用于获取...
7. **异常处理**:cx_Oracle模块提供了一套完整的异常处理机制,如`cx_Oracle.DatabaseError`,`cx_Oracle.IntegrityError`等,可以帮助开发者更好地处理可能出现的问题。 8. **安全考虑**:在使用cx_Oracle时,应...
6. **异常处理**:cx_Oracle提供了与Oracle相关的异常类,如DatabaseError、OperationalError等,方便捕获和处理数据库操作中的错误。 7. **事务控制**:支持开始、提交、回滚事务,确保数据的一致性和完整性。 8....
Oracle存储过程是数据库编程的重要组成部分,它允许程序员在数据库中执行复杂的业务逻辑和数据操作。这个"ORACLE存储过程学习源码"集合包含了从基础到高级的30个示例,是学习和掌握Oracle存储过程的理想资源。下面,...
批量提交在Oracle存储过程中是一项非常重要的技术,它可以帮助我们有效地处理大量数据,并且显著提升系统的整体性能。通过合理设计和实现,可以充分发挥其优势,为应用程序带来更好的用户体验。
cx_Oracle库支持各种数据库操作,包括事务控制、参数化查询、游标管理、异常处理等。对于更复杂的操作,如存储过程调用、批量插入、游标的使用,cx_Oracle也提供了相应的接口。 在Python 3.6环境下,cx_Oracle的这...
10. **Oracle特性支持**:包括Oracle的LOB(Large Object)操作、ROWID访问、触发器、存储过程调用、PL/SQL包的使用等。 综上所述,cx_Oracle-6.1.tar.gz文件是Python开发者连接Oracle数据库的重要工具,通过这个库...
Oracle存储过程是SQL与PL/SQL结合的强大功能,用于封装复杂的数据操作逻辑于数据库内部,从而实现高效的事务处理和数据管理。以下是对Oracle存储过程的一些关键知识点的深入解析: #### Oracle存储过程基本语法 ...
Oracle存储过程和函数是数据库管理中的重要组成部分,它们允许开发者创建复杂的业务逻辑和数据处理流程。在这个"Oracle存储过程函数生成DEMO"中,我们主要关注如何在Oracle数据库环境中设计、编写、测试以及调用存储...
Oracle存储过程是数据库管理系统中的一种重要特性,它允许开发者编写一系列SQL和PL/SQL语句,形成一个可重用的程序单元。存储过程在数据库中预先编译并存储,这样在执行时能提高效率,因为它避免了每次调用时的重新...
在本自学资料中,我们将深入探讨PL/SQL的基本概念、结构、流程控制、运算符与表达式、游标、异常处理、存储过程和函数、包以及触发器。 首先,PL/SQL的全称是Procedure Language & Structured Query Language,它是...
调用Oracle存储过程是数据库管理中的常见任务,尤其对于需要执行大量数据处理或事务操作的场景。下面我们将详细探讨如何在Oracle中调用存储过程以及其相关知识点。 1. **创建存储过程**: 在Oracle中,你可以使用`...
以下是一个简单的示例,展示了如何调用一个不带参数的Oracle存储过程: ```java Session session = sessionFactory.openSession(); Transaction transaction = session.beginTransaction(); session....
通过理解这些内容,你可以学习如何在Java应用中集成Oracle存储过程,从而实现更高效的数据操作和业务逻辑处理。在实际应用中,务必确保代码的健壮性、可读性和可维护性,这对于长期的项目维护至关重要。