1.日志表定义
日志一般会记录:同步的源表名,同步的目标表名,步骤名称,记录行数,状态,开始时间,结束时间,备注。
2.创建日志表
create table log_table ( source_table_name varchar2(100), target_table_name varchar2(100), step_name varchar2(100), row_count number, status varchar2(30), start_dt date, end_dt date, mark varchar2(100) );
3.开发往log_table同步数据的存储过程
create or replace procedure p_log( p_source_table_name varchar2, p_target_table_name varchar2, p_step_name varchar2, p_row_count number, p_status varchar2, p_start_dt date, p_end_dt date, p_mark varchar2) is begin insert into log_table values (p_source_table_name, p_target_table_name, p_step_name, p_row_count, p_status, p_start_dt, p_end_dt, p_mark); commit; ---异常 exception when others then dbms_output.put_line(sqlerrm); end; -- 调用存储过程 begin p_log(p_source_table_name, p_target_table_name, p_step_name, p_row_count, p_status, p_start_dt, p_end_dt, p_mark); end;
4.开发存储过程 emp同步数据到 emp_1135
drop table emp_1135; create table emp_1135 as select * from emp where 1 = 2; -- 给emp_1135表添加主键 alter table emp_1135 add constraint pk_emp_1135 primary key (empno); -- 创建存储过程 create or replace procedure p_19 as v_source varchar2(20); v_target varchar2(20); v_st date; v_dt date; v_ct number; begin v_st := sysdate; v_source := 'emp'; v_target := 'emp_1135'; insert into emp_1135 select * from emp; v_ct := sql%rowcount; commit; v_dt := sysdate; -- 调用日志表存储过程 p_log(p_source_table_name=>v_source, p_target_table_name=>v_target, p_step_name=>v_source || ' to ' || v_target, p_row_count=>v_ct, p_status=>'成功', p_start_dt=>v_st, p_end_dt=>v_dt, p_mark=>''); -- 定义异常 exception when others then p_log(p_source_table_name=>v_source, p_target_table_name=>v_target, p_step_name=>v_source || ' to ' || v_target, p_row_count=>0, p_status=>'失败', p_start_dt=>v_st, p_end_dt=>null, p_mark=>sqlerrm); end; -- 调用存储过程 begin p_19; end;
select * from emp_1135;
-- 查询日志表 select * from log_table;
再次调用存储过程
-- 调用存储过程 begin p_19; end;
select * from emp_1135;
-- 查询日志表 select * from log_table;
5.开发一个存储过程
将emp表同步到 emp_1134,然后将通过emp_1134这个表数据计算每个部门总薪资,同步到 emp_sum_sal
create table emp_1134 as select * from emp where 1=2; -- 添加主键 alter table emp_1134 add constraint pk_emp_1134 primary key (empno); create table emp_sum_sal (deptno number,sum_sal number);
create or replace procedure p_20 as v_st date; v_dt date; v_ct number; v_source varchar2(50); v_dir varchar2(50); begin v_source := 'emp'; v_dir := 'emp_1134'; v_st := sysdate; insert into emp_1134 select * from emp; v_ct := sql%rowcount; commit; v_dt := sysdate; p_log(p_source_table_name => v_source, p_target_table_name => v_dir, p_step_name => v_source || ' to ' || v_dir, p_row_count => v_ct, p_status => '成功', p_start_dt => v_st, p_end_dt => v_dt, p_mark => ''); ------------------------------------------------------- v_source := 'emp_1134'; v_dir := 'emp_sum_sal'; v_st := sysdate; insert into emp_sum_sal select deptno, sum(sal) from emp_1134 group by deptno; v_ct := sql%rowcount; commit; v_dt := sysdate; p_log(p_source_table_name => v_source, p_target_table_name => v_dir, p_step_name => v_source || ' to ' || v_dir, p_row_count => v_ct, p_status => '成功', p_start_dt => v_st, p_end_dt => v_dt, p_mark => ''); ---异常处理 exception when others then -- dbms_output.put_line(sqlerrm); -- raise; 可以添加弹窗 p_log(p_source_table_name => v_source, p_target_table_name => v_dir, p_step_name => v_source || ' to ' || v_dir, p_row_count => 0, p_status => '失败', p_start_dt => v_st, p_end_dt => null, p_mark => sqlerrm); end; begin p_20; end;
-- 查询日志表 select * from log_table;
select * from emp_1134;
select * from emp_sum_sal;
再次调用存储过程
begin p_20; end;
-- 查询日志表 select * from log_table;
select * from emp_1134;
select * from emp_sum_sal;
第二次调用存储过程时,因为emp_1134有主键,所以当第二次insert到emp_1134时检测到异常,直接抛出,不会往下走
6.日志表的功能
通过写日志表,能够记录存储过程哪一个步骤执行成功,哪一个步骤执行失败了,以及能记录 每个步骤的 执行时间,方便开发者后期对其优化,以及方便,检查。
- 日志的另一大功能点:程序报错的时候,记录程序报错的步骤 以及 错误的原因。
- 例如:存储过程的同步逻辑(比如源表有10条数据,日志表中记录,同步过去的行数有20条,说明sql中存在数据发散)
- 练习:全量同步 dept 表 到 dept_1123,并记录详细的日志信息,以及出现异常,则抛出。
----创建目标表 create table dept_1123 as select * from dept where 1 = 2; ----开发存储过程 create or replace procedure p_dept is v_rowcount number; v_start_dt date; v_end_dt date; begin v_start_dt := sysdate; ----清空目标表 execute immediate 'truncate table dept_1123'; -----插入数据 insert into dept_1123 select * from dept; v_rowcount := sql%rowcount; commit; v_end_dt := sysdate; p_log(p_source_table_name =>'dept', p_target_table_name => 'dept_1123', p_step_name =>'dept同步数据到dept_1123', p_row_count => v_rowcount, p_status => 'success', p_start_dt => v_start_dt, p_end_dt => v_end_dt, p_mark =>'执行成功'); -------异常处理 exception when others then dbms_output.put_line(sqlerrm); p_log(p_source_table_name =>'dept', p_target_table_name => 'dept_1123', p_step_name =>'dept同步数据到dept_1123', p_row_count => 0, p_status => 'fail', p_start_dt => v_start_dt, p_end_dt => null, p_mark =>sqlerrm); raise; end; ----调用 begin p_dept; end; ----验证 select * from dept_1123; select * from log_table;
7.日志表总结
日志表的模板 以及 调用写日志存储过程 在项目组中已经落地好了,我们直接开发存储过程里面的同步逻辑,然后对照着套着写日志就可以了。
日志的核心功能点:
- 1.记录存储过程每个步骤的 开始时间 & 结束时间,可以分析写的sql执行的效率高与低
- 2.记录每个步骤的执行状态,成功与否,方便我们快速找到报错的步骤
- 3.记录每个步骤的影响行数,验证程序能够准确跑出数据(如果行数为0,则说明没有跑出来数据)
- 4.记录详细的报错步骤以及错误原因,方便我们快速定位问题,解决问题
以上为个人经验,希望能给大家一个参考,也希望大家多多支持代码网。
发表评论