首页 > Oracle, PL/SQL > SAVEPOINT 在循环中的独立性

SAVEPOINT 在循环中的独立性

2019年11月24日 发表评论 阅读评论

官方对SAVEPOINT的说明:
Use the SAVEPOINT statement to identify a point in a transaction to which you can later roll back.
简单的理解就是可以部分提交事务
官网的一个例子:

UPDATE employees
    SET salary = 7000
    WHERE last_name = 'Banda';
SAVEPOINT banda_sal;

UPDATE employees
    SET salary = 12000
    WHERE last_name = 'Greene';

SAVEPOINT greene_sal;

SELECT SUM(salary) FROM employees;

ROLLBACK TO SAVEPOINT banda_sal;

UPDATE employees
    SET salary = 11000
    WHERE last_name = 'Greene';

COMMIT;

由于会滚到了banda_sal,所以到检查点banda_sal之间的对表的修改会回退。
如果在另一个循环里使用SAVEPOINT,每次循环会是独立的吗?

1. 创建两张表

create table T_A
(
  ID NUMBER
);

create table T_B
(
  NAME VARCHAR2(10)
);

2. 创建函数

--模拟当ID=3 插入失败
--在T_A中插入 1,2,3,4,5
CREATE OR REPLACE FUNCTION FUN_1(ID IN NUMBER) RETURN NUMBER IS
BEGIN

  IF ID = 3 THEN
    RETURN 1;
  ELSE
    dbms_output.put_line('Fun_1 参数id=' || id);
    INSERT INTO T_A VALUES (ID);
    RETURN 0;
  END IF;
END FUN_1;
--模拟当ID=4时插入失败
--在T_B中插入 'a', 'b', 'c' 'd', 'e'
CREATE OR REPLACE FUNCTION FUN_2(ID IN NUMBER) RETURN NUMBER IS
  V_VALUE VARCHAR2(10);
BEGIN
  SELECT DECODE(ID, 1, 'a', 2, 'b', 3, 'c', 4, 'd', 5, 'e', 'z')
    INTO V_VALUE
    FROM DUAL;

  IF ID = 4 THEN
    RETURN 1;
  ELSE
    dbms_output.put_line('Fun_2 参数id=' || id);
    INSERT INTO T_B VALUES (V_VALUE);
    RETURN 0;
  END IF;
END FUN_2;

3. 测试

--在开始调用FUN_1和FUN_2之前先建立保存点
--如果FUN_1或者FUN_2发生异常,本次循环就需要回退
--Oracle 10g不支持continue 使用goto模拟了continue
DECLARE
  V_CODE1 INTEGER;
  V_CODE2 INTEGER;
BEGIN
  FOR I IN 1 .. 5 LOOP
    SAVEPOINT BANDA_SAL;
    V_CODE1 := FUN_1(I);
    IF V_CODE1 != 0 THEN
      GOTO ERROR_LOOP;
    END IF;
    V_CODE2 := FUN_2(I);
    IF V_CODE2 != 0 THEN
      GOTO ERROR_LOOP;
    END IF;
    <<ERROR_LOOP>>
    IF V_CODE1 != 0 OR V_CODE2 != 0 THEN
      ROLLBACK TO SAVEPOINT BANDA_SAL;
    END IF;
    NULL;
  END LOOP;
  COMMIT;
END;

4. 运行结果

由于当ID=3 和ID=4的时候都发生的回滚,每张表应该
只有3条数据:

SELECT * FROM t_a;
1
2
5
SELECT * FROM t_b;
a
b
e

5.结论

SAVEPOINT在循环中也是独立的。

分类: Oracle, PL/SQL 标签:
  1. 本文目前尚无任何评论.
  1. 本文目前尚无任何 trackbacks 和 pingbacks.