PL/SQL 训练04--事务

1. 第三课作业中第二题的异常记录方法,大家可以完善下方法,将之改成支持自治事务的方法。
2. 这段程序中,ma_users是第一课作业建立的用户表,这段程序的目的是,一旦用户注册成功,在其默认积分基础上送1000积分。但程序里有BUG,请大家找出来,并且优化这个程序

create or replace procedure save_user(i_user ma_users%rowtype) is   
begin
  insert into ma_users values i_user;
exception
  when dup_val_on_index then
    update ma_users t
       set row = i_user
     where t.user_name = i_user.user_name;
end;
/
create or replace PROCEDURE UPDATE_USER(I_USER  IN VARCHAR2,
                                        i_point in number) IS
  PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
  UPDATE MA_USERS R
     SET R.USER_POINT = R.USER_POINT + i_point
   WHERE R.USER_NAME = I_USER;
    dbms_output.put_line('test1');
  COMMIT;
END UPDATE_USER;
declare
  v_user ma_users%rowtype;
begin
  v_user.created_by      := 'system';
  v_user.created_date    := sysdate;
  v_user.updated_by      := 'system';
  v_user.updated_date    := sysdate;
  v_user.id_ma_users     := sys_guid();
  v_user.user_name       := '幸运小子1';
  v_user.user_password   := 'text123';
  v_user.user_sex        := '1';
  v_user.user_phone      := '233sss33';
  v_user.real_name       := 'xinyuan';
  v_user.identity_no     := '22222';
  v_user.user_email      := '[email protected]';
  v_user.user_address    := 'hhhhhhh';
  v_user.user_birth_date := date '1986-01-01';
  v_user.user_status     := '1';
  v_user.user_remark     := 'sss';
  v_user.user_point      := 100;
  v_user.register_date   := sysdate;
  save_user(v_user);
  UPDATE_USER('幸运小子1', 1000);
end;
/
3.【可选做】 这节讲到了MERGE的语句,请大家改写这个语句,实现如果存在则更新,不存在则插入的逻辑,注意PLSQL程序要有异常处理

--
1 修改成自治事务
PROCEDURE exception_logs_p (
      i_option_users        IN exception_logs.option_users%TYPE,
      i_method_name         IN exception_logs.method_name%TYPE,
      i_exception_line      IN exception_logs.exception_line%TYPE,
      i_exception_code      IN exception_logs.exception_code%TYPE,
      i_exception_message   IN exception_logs.exception_message%TYPE--i_exception_level    IN exception_logs.exception_level%TYPE
      )
   IS
      PRAGMA AUTONOMOUS_TRANSACTION;
      v_sysdate           DATE DEFAULT SYSDATE;
      v_exception_level   NUMBER DEFAULT 0;
 BEGIN     
  BEGIN
   SELECT   exception_level
      INTO v_exception_level
     FROM exception_level
      WHERE exception_code=i_exception_code;
      
   EXCEPTION 
   WHEN OTHERS THEN
    v_exception_level:=3;
    END ;
    
   BEGIN
      INSERT INTO exception_logs (option_users,
                                  method_name,
                                  exception_time,
                                  exception_line,
                                  exception_code,
                                  exception_message,
                                  exception_level)
           VALUES (i_option_users,
                   i_method_name,
                   v_sysdate,
                   i_exception_line,
                   i_exception_code,
                   i_exception_message,
                   v_exception_level);

      COMMIT;
   EXCEPTION
      WHEN OTHERS
      THEN
         ROLLBACK;
   END;
  END;
END exception_logs_pkg;
/

2 程序bug
1 由于UPDATE_USER过程使用了自治事务,这与主事务隔离开,主事务的insert没有提交,
导致UPDATE_USER没有获取到数据,导致数据更新错误
修改:1 可以在save_user上加上commit
2 取消UPDATE_USER的自治事务

3 

declare
  v_user ma_users%rowtype;
  v_usero varchar2(32) default user;
  v_erroeline varchar2(100);--not a number
  v_sqlcode number;
  v_sqlerrm varchar2(100);
begin
  v_user.created_by      := 'system';
  v_user.created_date    := sysdate;
  v_user.updated_by      := 'system';
  v_user.updated_date    := sysdate;
  v_user.id_ma_users     := sys_guid();
  v_user.user_name       := '乱世佳人12';
  v_user.user_password   := 'text123';
  v_user.user_sex        := '1';
  v_user.user_phone      := '233sss3311';
  v_user.real_name       := 'xinyuan';
  v_user.identity_no     := '22222';
  v_user.user_email      := '[email protected]';
  v_user.user_address    := 'hhhhhhh';
  v_user.user_birth_date := date '1986-01-01';
  v_user.user_status     := '1';
  v_user.user_remark     := 'sss';
  v_user.user_point      := 100;
  v_user.register_date   := sysdate;
begin  
--register user
merge into MA_USERS m1
using( select count(id_ma_users) d from MA_USERS where user_name=v_user.user_name) m2
on (m2.d<>0)
--when matched then
 --update set m1.USER_POINT=m1.USER_POINT+1000,updated_date=sysdate 
 --where  user_name=v_user.user_name
when not matched then
 insert   values v_user ;
 --update point
 merge into MA_USERS m1
using( select m2.id_ma_users d from MA_USERS m2 where m2.id_ma_users=v_user.id_ma_users ) m2
on (m2.d=m1.id_ma_users)
when matched then
 update set m1.USER_POINT=m1.USER_POINT+1000,updated_date=sysdate ;
  dbms_output.put_line('v_user.id_ma_users='||v_user.id_ma_users);
 dbms_output.put_line('t1');
exception
 when others then
 v_erroeline:=dbms_utility.format_error_backtrace;
    v_sqlcode:=sqlcode;
    v_sqlerrm:=substr(SQLERRM,1,100);
  exception_logs_pkg.exception_logs_p (v_usero,'testerror',v_erroeline,v_sqlcode, v_sqlerrm); 
      RAISE; 
end;
commit;
end;
/

猜你喜欢

转载自www.cnblogs.com/yhq1314/p/10613204.html