Oracle存储过程记录异常日志

  一般我们会将一些涉及到数据库的定时任务直接用存储过程搞定,省去了后端代码的开发、部署,简单、快速,但这种方式存在一个弊端——当存储过程执行出错了,我们无法感知。解决办法也简单,学代码那样去捕获异常、打印日志。

  第一步,建日志表:

create table TBL_WLF_SYS_LOG
(
      S_TIME            VARCHAR2(32) not null,
    S_LEVEL            VARCHAR2(32),
    S_PROCNAME        VARCHAR2(64),
    S_MSG            VARCHAR2(4000),
    S_ADVICE        VARCHAR2(1024)
)
tablespace TBS_WLF_DAT;
-- Add comments to the table 
comment on table TBL_WLF_SYS_LOG
  is '存储过程日志表';
-- Add comments to the columns 
comment on column TBL_WLF_SYS_LOG.S_TIME
  is '操作时间';
-- Add comments to the columns 
comment on column TBL_WLF_SYS_LOG.S_LEVEL
  is '操作级别';
-- Add comments to the columns 
comment on column TBL_WLF_SYS_LOG.S_PROCNAME
  is '执行存储过程名称';
-- Add comments to the columns 
comment on column TBL_WLF_SYS_LOG.S_MSG
  is '错误信息';
-- Add comments to the columns 
comment on column TBL_WLF_SYS_LOG.S_ADVICE
  is '建议信息';

  第二步,建日志存储过程:

CREATE OR REPLACE PROCEDURE VCODE.prc_wlf_sys_writelog(
  i_flag       INTEGER,
  i_id         INTEGER,
  str_procname varchar2,
  str_msg      varchar2,
  str_advice   varchar2
) IS
  -- 操作时间
  str_time   varchar2(32);
  -- 操作级别
  str_level  varchar2(32);
  -- 执行存储过程名称
  p_procname varchar2(1024);
  -- 错误信息,或者记录信息
  p_msg      varchar2(1024);
  -- 建议信息
  p_advice   varchar2(1024);

BEGIN
  IF (i_flag = 2 AND i_id >= 1 AND i_id <= 4) THEN
    CASE
      WHEN i_id = 1 THEN
        str_level := 'log';
      WHEN i_id = 2 THEN
        str_level := 'debug';
      WHEN i_id = 3 THEN
        str_level := 'alarm';
      ELSE
        str_level := 'error';
    END CASE;
    p_procname := str_procname;
    p_msg      := str_msg;
    p_advice   := str_advice;
  ELSE
    str_level  := 'error';
    p_procname := 'p_public_writelog';
    p_msg      := 'writelog_error';
    p_advice   := '';
  END IF;

  str_time := to_char(SYSDATE, 'yyyy-mm-dd hh24:mi:ss');

  INSERT INTO tbl_wlf_sys_log
    (s_time, s_level, s_procname, s_msg, s_advice)
  VALUES
    (str_time, str_level, p_procname, p_msg, p_advice);
  COMMIT;
END prc_wlf_sys_writelog;
/

  第三步,在我们业务存储过程中,调用日志存储过程:

CREATE OR REPLACE procedure VCODE.PROC_CUSTOM_RECORD_UPDATE
is
  -- debug信息
    v_debugmsg      varchar2(1024);
  -- 错误信息
    v_errmsg      varchar2(1024);
  -- 查询用户邀请活动信息表 获取活动开始与结束时间
  cursor ACTIVITY_CUR
    is --声明显式游标
      select T.ACTIVITYID,
        T.COUNTSTARTTIME,
        T.COUNTENDTIME
      from vcode.T_INVITE_ACTIVITYINFO T
      where T.HASCOUNTTIME = 1;
  --定义游标变量,该变量的类型为基于游标ACTIVITY_CUR的记录
  type ACTIVITY_CUR_ROW is table of ACTIVITY_CUR%ROWTYPE; 
    cs_invitestat SYS_REFCURSOR;
  type tp_CUSTOM_RECORD is table of T_INVITER_CUSTOM_RECORD%ROWTYPE;
  va_CUSTOM_RECORD tp_CUSTOM_RECORD;
  ACTIVITY_ID varchar2(50);
  START_TIME  date;
  END_TIME    date;
begin
  -- 存储过程开始日志
  v_debugmsg := 'VCODE.PROC_CUSTOM_RECORD_UPDATE begin  log- ';
  prc_wlf_sys_writelog(2, 2, 'PROC_CUSTOM_RECORD_UPDATE', v_debugmsg, '');
  --For 循环  遍历用户邀请活动信息表,根据活动开始结束时间间隔获取数据信息
  for ACTIVITY_CUR_ROW in ACTIVITY_CUR
  LOOP
  ACTIVITY_ID := ACTIVITY_CUR_ROW.ACTIVITYID;
    START_TIME  := ACTIVITY_CUR_ROW.COUNTSTARTTIME;
    -- 取当天的最后一秒
    select TRUNC(ACTIVITY_CUR_ROW.COUNTENDTIME+1)-1/(24*3600)
    into END_TIME
    from DUAL;
    -- 根据活动ID,开始时间,结束时间,查询被邀请人记录表获取邀请人激活人数与最后激活时间,查询奖励记录表获取书券奖励,并关联一起。
    open cs_invitestat for 
    SELECT t4.INVITERMSISDN,COUNT(1) AS TOTALACTIVENUMBER,max(t4.ACTIVETIME) AS LASTACTIVETIME,t4.ACTIVITYID,CASE WHEN SUM(t3.PRIZENUM) is null THEN 0 ELSE SUM(t3.PRIZENUM) END  totalTicket  
    FROM (    
      SELECT t1.INVITERMSISDN,t1.INVITEEMSISDN,t1.ACTIVETIME,t1.ACTIVITYID   FROM T_INVITEE_RECORD t1
        WHERE t1.ACTIVITYID=ACTIVITY_ID
                  and t1.ACTIVESTATUS = 1
                  and t1.INVITEETYPE = 0
                  and t1.ACTIVETIME <= END_TIME
                  and t1.ACTIVETIME    >= START_TIME ) t4
     LEFT JOIN
     (SELECT t2.INVITERMSISDN,t2.INVITEEMSISDN,SUM(t2.PRIZENUM) PRIZENUM,t2.ACTIVETIME  
      FROM T_INVITING_AWARDS_RECORD t2
       WHERE t2.PRIZETYPE=3 AND t2.ISSEND IN (0,1,2,3,10)
            AND t2.ACTIVITYID=ACTIVITY_ID
            and t2.ACTIVETIME <= END_TIME
            and t2.ACTIVETIME    >= START_TIME
            and t2.REWARDTYPE = 0 
            group by t2.ACTIVETIME,t2.INVITEEMSISDN,t2.INVITERMSISDN) t3
    ON t4.INVITERMSISDN=t3.INVITERMSISDN  AND t4.INVITEEMSISDN=t3.INVITEEMSISDN   AND   t4.ACTIVETIME=t3.ACTIVETIME 
    group by t4.ACTIVITYID,t4.INVITERMSISDN 
    ORDER BY TOTALACTIVENUMBER desc,LASTACTIVETIME ASC;
    fetch cs_invitestat bulk collect into va_CUSTOM_RECORD limit 500;
    -- 遍历结果,并插入T_INVITER_CUSTOM_RECORD 自定义排行表中,如果存在数据则更新(邀请人、活动ID相同),不存在则插入
    forall i in 1..va_CUSTOM_RECORD.count
    merge into vcode.T_INVITER_CUSTOM_RECORD T5
      using (select * from dual)
      on (INVITERMSISDN = va_CUSTOM_RECORD(i).INVITERMSISDN AND ACTIVITYID=va_CUSTOM_RECORD(i).ACTIVITYID)
    when matched then
        update
          set TOTALACTIVENUMBER      =va_CUSTOM_RECORD(i).TOTALACTIVENUMBER,
            LASTACTIVETIME           =va_CUSTOM_RECORD(i).LASTACTIVETIME,
            TOTALTICKET           =va_CUSTOM_RECORD(i).TOTALTICKET
          where T5.TOTALACTIVENUMBER!=va_CUSTOM_RECORD(i).TOTALACTIVENUMBER OR T5.TOTALTICKET!=va_CUSTOM_RECORD(i).TOTALTICKET
    when not matched then
        insert
          (
            INVITERMSISDN,
            TOTALACTIVENUMBER,
            LASTACTIVETIME,
            ACTIVITYID,
            TOTALTICKET
          )
          values
          (
            va_CUSTOM_RECORD(i).INVITERMSISDN,
            va_CUSTOM_RECORD(i).TOTALACTIVENUMBER,
            va_CUSTOM_RECORD(i).LASTACTIVETIME,
            va_CUSTOM_RECORD(i).ACTIVITYID,
            va_CUSTOM_RECORD(i).TOTALTICKET
          );
        commit;
  end LOOP;
  -- 存储过程开始日志
  v_debugmsg := 'VCODE.PROC_CUSTOM_RECORD_UPDATE end  log- ';
  prc_wlf_sys_writelog(2, 2, 'PROC_CUSTOM_RECORD_UPDATE', v_debugmsg, '');
exception
  when others then
    begin
      rollback;
      v_errmsg := 'sqlexception~~sqlcode:' || to_char(sqlcode) ||
                  ' sqlstate:' || substr(sqlerrm, 1, 512);
      prc_wlf_sys_writelog(2, 4, 'PROC_CUSTOM_RECORD_UPDATE', v_errmsg, '');
    end;
end;
/

 

posted on 2018-10-22 17:12  不想下火车的人  阅读(10816)  评论(0编辑  收藏  举报

导航