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>

 



 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值