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; /