读书人

oracle初记之事物(Procedure)

发布时间: 2012-08-28 12:37:01 作者: rapoo

oracle小记之事物(Procedure)

oracle的自定义事物(Procedure)一般是用DBMS_JOBS来调,也可以写个定时器调用。

以下是事物涉及的常用语法,自己看,不解释。。。

CREATE OR REPLACE PROCEDURE PRO_SYNCHRO_A_TO_B/************创建时间XXXX-XX-XX**********************************把A系统的用户表A_USER数据同步到B系统的用户表B_USER中*****************************************************/IS    --定义未同步A的A_USER表数据数量    v_a_count NUMBER(15);    /****异常定义*****/    v_err_msg VARCHAR2(1024);    -- 没有找需要到的数据异常    not_a_user_data_ex EXCEPTION;BEGIN    --查询需要导出A_USER用户数量    SELECT COUNT(1) INTO v_a_count FROM A_USER A WHERE    NOT EXISTS(        SELECT 1 FROM B_USER B WHERE B.ID = A.ID    );    IF v_a_count<=0 THEN        --没有要导入的数据        RAISE not_a_user_data_ex;    END IF;    --数据导入    INSERT INTO B_USER(ID,USERNAME,PASSWORD)SELECT ID,USERNAME,PASSWORD FROM A_USER WHERE    NOT EXISTS(        SELECT 1 FROM B_USER B WHERE B.ID = A.ID            );    --写入日志    INSERT INTO T_LOG(EXEC_TIME,EXEC_PRC_NAME,ERROR_MSG,EXEC_ACTION,EXEC_STATUS)    VALUES(SYSDATE,'PRO_SYNCHRO_A_TO_B',NULL,'同步A_USER数据#'||v_a_count||'#条','0');    --提交数据    COMMIT;--异常处理EXCEPTION    WHEN not_a_user_data_ex THEN        ROLLBACK;         --写入日志        INSERT INTO T_LOG(EXEC_TIME,EXEC_PRC_NAME,ERROR_MSG,EXEC_ACTION,EXEC_STATUS)        VALUES(SYSDATE,'PRO_SYNCHRO_A_TO_B',NULL,'同步A_USER数据0条','0');        --提交日志数据        COMMIT;    WHEN others THEN        ROLLBACK;        --写入日志        v_err_msg:=SQLERRM;        INSERT INTO T_LOG(EXEC_TIME,EXEC_PRC_NAME,ERROR_MSG,EXEC_ACTION,EXEC_STATUS)        VALUES(SYSDATE,'PRO_SYNCHRO_A_TO_B',v_err_msg,'同步A_USER失败','1');        --提交日志数据        COMMIT;END;

顺道引网友(http://www.cnblogs.com/ITtangtang/archive/2012/04/23/2466554.html)的例子说明一下事物的一致性和只读属性。

一、事务概念
事务用于保证数据的一致性,它由一组相关的dml语句组成,该组的dml(数据操作语言,增删改,没有查询)语句要么全部成功,要么全部失败。如:网上转账就是典型的要用事务来处理,用于保证数据的一致性。

二、java程序中如何使用事务
在java操作数据库时,为了保证数据的一致性,比如账户操作(1)从一个账户中减掉10$(2)在另一个账户上加入10$,我们看看如何使用事务?

package junit.test;import java.sql.Connection;import java.sql.DriverManager;import java.sql.SQLException;import java.sql.Statement;public class TransationTest {    public static void main(String[] args) {        Connection conn = null;        try {            // 1.加载驱动            Class.forName("oracle.jdbc.driver.OracleDriver");            // 2.得到连接            conn = DriverManager.getConnection("jdbc:oracle:thin:@127.0.0.1:1521:orcl", "SCOTT", "scott");            Statement sm = conn.createStatement();            // 从scott的sal中减去100            sm.executeUpdate("update emp set sal=sal-100 where ename='SCOTT'");            int i = 7 / 0; //报java.lang.ArithmeticException: / by zero异常            // 给smith的sal加上100            sm.executeUpdate("update emp set sal=sal+100 where ename='SMITH'");            // 关闭打开的资源            sm.close();            conn.close();        } catch (Exception e) {            // 如果发生异常,就回滚            try {                conn.rollback();            } catch (SQLException e1) {                e1.printStackTrace();            }            e.printStackTrace();        }    }}


运行,会出现异常,查看数据库,SCOTT 的sal 减了100,但是SMITH 的sal 却不变,很可怕。。。我们怎样才能保证,这两个操作要么同时成功,要么同时失败呢?

package junit.test;import java.sql.Connection;import java.sql.DriverManager;import java.sql.SQLException;import java.sql.Statement;public class TransationTest {    public static void main(String[] args) {        Connection conn = null;        try {            // 1.加载驱动            Class.forName("oracle.jdbc.driver.OracleDriver");            // 2.得到连接            conn = DriverManager.getConnection("jdbc:oracle:thin:@127.0.0.1:1521:orcl", "SCOTT", "scott");            // 加入事务处理            conn.setAutoCommit(false);// 设置不能默认提交            Statement sm = conn.createStatement();            // 从scott的sal中减去100            sm.executeUpdate("update emp set sal=sal-100 where ename='SCOTT'");            int i = 7 / 0;            // 给smith的sal加上100            sm.executeUpdate("update emp set sal=sal+100 where ename='SMITH'");            // 提交事务            conn.commit();            // 关闭打开的资源            sm.close();            conn.close();        } catch (Exception e) {            // 如果发生异常,就回滚            try {                conn.rollback();            } catch (SQLException e1) {                e1.printStackTrace();            }            e.printStackTrace();        }    }}


再运行一下,会出现异常,查看数据库,数据没变化。。

三、只读事务
只读事务是指只允许执行查询的操作,而不允许执行任何其它dml操作的事务,使用只读事务可以确保用户只能取得某时间点的数据。假定机票代售点每天18点开始统计今天的销售情况,这时可以使用只读事务。在设置了只读事务后,尽管其它会话可能会提交新的事务,但是只读事务将不会取得最新数据的变化,从而可以保证取得特定时间点的数据信息。
设置只读事务: set transaction read only;

比如有两个用户system、scott各自用sqlplus登陆,操作如下:
第一步:用system用户登陆sqlplus,设置只读事务。
SQL> set transaction read only;
事务处理集。

第二步:用scott用户登陆sqlplus,操作如下:
SQL> select count(*) from emp; --查询emp表的总记录数
COUNT(*)
----------
13

SQL> insert into emp values (7777, 'zhangsan', 'MANAGER', 7782, to_date('1988-02-18', 'yyyy-mm-dd'), 38.38, 45.45, 10); --插入一条记录到emp表
1 row inserted

SQL> select count(*) from emp; --查询emp表的总记录数
COUNT(*)
----------
14

SQL> commit; --提交
Commit complete

第三步:用system用户查询scott.emp表
SQL> select count(*) from scott.emp;
COUNT(*)
----------
13
SQL>



读书人网 >其他数据库

热点推荐