Oracle存储过程记录异常日志
一般我们会将一些涉及到数据库的定时任务直接用存储过程搞定,省去了后端代码的开发、部署,简单、快速,但这种方式存在一个弊端——当存储过程执行出错了,我们无法感知。解决办法也简单,学代码那样去捕获异常、打印日志。
第一步,建日志表:
create table TBL_WLF_SYS_LOG
(
S_TIME VARCHAR2() not null,
S_LEVEL VARCHAR2(),
S_PROCNAME VARCHAR2(),
S_MSG VARCHAR2(),
S_ADVICE VARCHAR2()
)
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;
/
Oracle存储过程记录异常日志的更多相关文章
- Oracle存储过程记录异常
--建立错误日志表 create table PUB_PROC_ERR_LOG ( LOG_ID NUMBER, MODULE_NAME ), PROC_NAME ), ERR_TIME DATE, ...
- Oracle存储过程中异常Exception的捕捉和处理
Oracle存储过程中异常的捕捉和处理 CREATE OR REPLACE Procedure Proc_error_process ( v_IN in Varchar2, v_OUT Out Var ...
- 项目中oracle存储过程记录——经常使用语法备忘
项目中oracle存储过程记录--经常使用语法备忘 项目中须要写一个oracle存储过程,需求是收集一个复杂查询的内容(涉及到多张表),然后把符合条件的记录插入到目标表中.当中原表之中的一个的日期字段 ...
- oracle存储过程获取异常信息码和异常信息
oracle存储过程,可以通过sqlcode 获取异常编码.通过sqlerrm获取异常信息. 例子: create or replace procedure write2blob(p_id in nu ...
- 在 C# 控制台中记录异常日志并输出
最近做了一个小程序,要求在控制台中记录程序运行的异常并输出到指定的文件夹中,以下是我的具体的程序代码: public static void ErrorLog(Exception ex) { stri ...
- MVC4.0 利用HandleErrorAttribute和log4net实现记录异常日志功能
1.MVC4.0中HandleErrorAttribte已经帮我们处理了异常问题,当我们新建一个非空的MVC项目时候,在FilterConfig中会发现这样的代码 public class Filte ...
- MVC中使用过滤器记录异常日志
using System; using System.Collections.Generic; using System.Linq; using System.Web; namespace Filte ...
- 在ASP.NET MVC中使用Log4Net记录异常日志,出错时导向到静态页
本篇体验在ASP.NET MVC 4中使用Log4Net记录日志. 通过NuGet安装Log4Net. 需求是:当出错时导向到Error.html静态页面,Log4Net记录错误信息. 大致的思路是: ...
- ASP.NET全局错误处理和异常日志记录以及IIS配置自定义错误页面
应用场景和使用目的 很多时候,我们在访问页面的时候,由于程序异常.系统崩溃会导致出现黄页.在通常的情况下,黄页对于我们来说,帮助是极大的,因为它可以帮助我们知道问题根源,甚至是哪一行代码出现了错误.但 ...
随机推荐
- 【Error】IOError: [Errno 22] invalid mode ('wb') or filename
错误描述: IOError: [Errno 22] invalid mode ('wb') or filename: 'C:\\Users\\Viral Patel\\Documents\\GitHu ...
- field字段错位手动更改方法
update tbprotocolex set field='1' where name='ICMP';update tbprotocolex set field='1' where name='DN ...
- 深入理解java泛型
一. 什么是泛型? 泛 型(Generic type 或者 generics)是对 简单的理解,就是对类型的参数化,比如我们定义一个类属性或者实例属性时,往往要指定具体的类型,如Integer.Per ...
- vue的v-model绑定数据问题
在我的项目中有一个这样的功能模块: 我们修改数据全是在前台的table中修改,然后把这个table的值带到后台.(理想:修改值后,点击确认值改变,点击取消值恢复原来的值)那么问题就来了: a)你修改值 ...
- Java基础学习-接口-概述以及成员特点
package interfaceclass; /*接口的概述: * 接口解决的问题: * 因为java中的继承的单一局限性(子类只能继承一个父类),为了打破这个局限,java语言提供了一个机制,接口 ...
- VPS安装metasploit-framework
一.安装过程 在/etc/apt/sources.list添加kali源: root@localhost:~# cat >> /etc/apt/sources.list << ...
- 设计 react 组件
重新设计 React 组件库 诚身 7 个月前 在 react + redux 已经成为大部分前端项目底层架构的今天, 让我们再次回到软件工程界一个永恒问题的探讨上来, 那就是如何提升一个开发团队 ...
- vue.js 源代码学习笔记 ----- instance event
/* @flow */ import { updateListeners } from '../vdom/helpers/index' import { toArray, tip, hyphenate ...
- http和https区别
超文本传输协议 HTTP 协议被用于在 Web 浏览器和网站服务器之间传递信息,HTTP 协议以明文方式发送内容,不提供任何方式的数据加密,如果攻击者截取了 Web 浏览器和网站服务器之间的传输报文, ...
- Kotlin Reference (三) Coding Conventions
most from reference 命名规则 1.使用驼峰式命名规则,尽量避免在命名中使用下划线 2.类型以大写字母开头 3.方法和属性以小写字母开头 4.使用4个空格缩进 5.public的方法 ...