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配置自定义错误页面
应用场景和使用目的 很多时候,我们在访问页面的时候,由于程序异常.系统崩溃会导致出现黄页.在通常的情况下,黄页对于我们来说,帮助是极大的,因为它可以帮助我们知道问题根源,甚至是哪一行代码出现了错误.但 ...
随机推荐
- Java环境搭建---(基础)
首先下载eclipse开发工具,下载地址:http://www.eclipse.org/downloads/,界面如下: 选择eclipse juno(4.2)的版本进入界面 点击Downloads, ...
- laravel中修改默认时区
在config文件夹下app.php中找到timezone,有RTC改成PRC
- 十一、dbms_random(随机数生成器)
1.概述 提供了内置的随机数生成器,可以用于快速生成随机数. 2.包的组成 1).initialize作用:用于初始化dbms_random包,必须提供随机数种子.语法:dbms_random.ini ...
- mysql主从复制跳过错误
mysql主从复制,经常会遇到错误而导致slave端复制中断,这个时候一般就需要人工干预,跳过错误才能继续 跳过错误有两种方式: 1.跳过指定数量的事务: mysql>slave stop; m ...
- C#学习历程(四)[实际问题]
>>无法直接启动带有”类库输出类型”的项目 在编辑界面的右侧会出现[解决方案资源管理器],里面显示我们的程序项目和所有代码文件. 右键点击项目,在右键菜单中选择[属性] 一般导致该问题都是 ...
- poj3686
题解: KM算法 把每一个点拆成n个 然后改变编圈 代码: #include<cstdio> #include<cmath> #include<cstring> # ...
- pgpool安装配置整理
安装PostgreSQL并配置三节点流复制环境,就不仔细说了,大致步骤如下: 1.下载源码 2.解压安装,如果在./configure --prefix=/usr/pgsql-10执行时提示要--wi ...
- Linux:更改hostname主机名
更改hostname主机名 查看主机名 hostname 临时更改主机名 hostname youname 更改永久生效主机名 1)更改配置文件 vi /etc/sysconfig/network 2 ...
- Getting command line access to PHP and MySQL running MAMP on OSX
建立自己profile路径应该在/Users/yourname/,最后要运行. ./.profile使文件生效,和windows中给添加环境变量是一个道理,还可以看出linux和UNIX默认运行路径为 ...
- C++解决error C4996报错
今天用c++写了个数独程序,在编译过程中报了一个错误: 1>------ 已启动生成: 项目: sudoku, 配置: Debug Win32 ------1> main.cpp1> ...