oracle存储过程实现定时备份表和处理重复数据

执行时 打印:dbms_output.put_line ( ‘11111111111’ );
拼接的动态sql 可以用 execute immediate 后面 加拼接的语句,下面有类似;
可以定义变量,然后 使用 into + 变量来使用;
异常 可以使用:EXCEPTION WHEN others THEN

一、整体流程说明

1. 首先创建了个日志错误表记录错误信息;

2. 创建一个通用的记录存储过程执行的错误记录(record_proc_err_log)

3. 创建一个处理备份表的存储过程:

删除7天以前的备份表,创建一个当天新的备份表(DAILY_BACKUP)

4. 创建存储过程:处理备份表和 处理重复数据(PROCESS_DUPLICATE_DATA)

4.1 查看重复数据,
4.2 如果有重复数据,则删除存在的备份表,创建新的备份表 ;无重复数据 则不执行任何处理
4.3 查询 备份表 是否和 原表一致(一致说明备份数据完整,可以处理重复数据了) ,不一致则不处理 (说明数据备份不完整)

5. 捕获异常信息,记录到存储过程执行的日志表中

6. 创建一个定时任务 去执行处理重复数据的存储过程(配置的每日凌晨 12点 执行)

二、脚本说明

1. 创建存储过程执行错误记录表和记录错误的存储过程;

--1.建立执行错误日志表
CREATE TABLE SYS_PUB_PROC_ERR_LOG (
	LOG_ID NUMBER,
	MODULE_NAME VARCHAR2 ( 100 ),
	PROC_NAME VARCHAR2 ( 100 ),
	TIME DATE,
	SQL_CODE VARCHAR2 ( 50 ),
	SQL_ERRM VARCHAR2 ( 100 ),
	ERR_CONTENT VARCHAR2 ( 500 ) 
);
COMMENT ON COLUMN SYS_PUB_PROC_ERR_LOG.LOG_ID IS '主键';
COMMENT ON COLUMN SYS_PUB_PROC_ERR_LOG.MODULE_NAME IS '模块名称';
COMMENT ON COLUMN SYS_PUB_PROC_ERR_LOG.PROC_NAME IS '存储过程名称';
COMMENT ON COLUMN SYS_PUB_PROC_ERR_LOG.TIME IS '时间';
COMMENT ON COLUMN SYS_PUB_PROC_ERR_LOG.SQL_CODE IS 'SQLCODE';
COMMENT ON COLUMN SYS_PUB_PROC_ERR_LOG.SQL_ERRM IS 'SQLERRM';
COMMENT ON COLUMN SYS_PUB_PROC_ERR_LOG.ERR_CONTENT IS '报错的具体行';

--2.表主键的序列
CREATE sequence SEQ_RECORD_PROC_ERR minvalue 1 maxvalue 9999999999999999999999999999 START WITH 21 INCREMENT BY 1 cache 20;

--3.通用记录错误存储过程
CREATE 
	OR REPLACE PROCEDURE record_proc_err_log ( module_name VARCHAR2, proc_name VARCHAR2, v_SQLCODE VARCHAR2, v_SQLERRM VARCHAR2, v_err_line VARCHAR2 ) IS PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
		INSERT INTO sys_pub_proc_err_log ( log_id, module_name, proc_name, time, sql_code, sql_errm, err_content )
	VALUES
		( seq_record_proc_err.nextval, module_name, proc_name, SYSDATE, v_SQLCODE, v_SQLERRM, v_err_line );
	commit;
	
END record_proc_err_log;

2. 处理备份表 :定期删除备份表(7天),并创建新的备份表

create or replace PROCEDURE DAILY_BACKUP AS

v_now VARCHAR2(8);

v_seven varchar2(8);

v_7tab1_has int;

v_table_name_1 CONSTANT VARCHAR2(50) := 'eval_sum_newest_info_bak_';

BEGIN

--获取当天日期

select to_char(SYSDATE, 'YYYYMMDD')

into v_now

from dual;

--获取7天前日期

select to_char(TRUNC(SYSDATE -7), 'YYYYMMDD')

into v_seven

from dual;

--删除7天前的表

select count(1) into v_7tab1_has from user_tables where TABLE_NAME = upper(v_table_name_1  || v_seven);

if v_7tab1_has=1 then

--如果存在,则执行drop table  (drop 是不能回滚的)
dbms_output.put_line ( '删除的表, '|| v_table_name_1  || v_seven );
execute immediate 'drop table '|| v_table_name_1  || v_seven;

end if;

--创建当天的数据备份
dbms_output.put_line ( 'CREATE TABLE ' || v_table_name_1  || v_now || ' AS SELECT * FROM eval_sum_newest_info');
EXECUTE IMMEDIATE 'CREATE TABLE ' || v_table_name_1  || v_now || ' AS SELECT * FROM eval_sum_newest_info';

COMMIT;
			EXCEPTION 
				WHEN others THEN
				record_proc_err_log ( 'process', 'data', SQLCODE, SQLERRM, substr( dbms_utility.format_error_backtrace, 1, 400 ) );
			ROLLBACK;
			
END DAILY_BACKUP;

3. 处理重复数据的存储过程;

-- 创建存储过程 先调用处理备份表,然后 处理重复数据
CREATE 
	OR REPLACE PROCEDURE PROCESS_DUPLICATE_DATA IS -- 定义变量
row1 NUMBER;
row2 NUMBER;
v_now VARCHAR2 ( 8 );
v_table_name_1 CONSTANT VARCHAR2 ( 50 ) := 'eval_sum_newest_info_bak_';
BEGIN--获取当天日期
	SELECT
		to_char( SYSDATE, 'YYYYMMDD' ) INTO v_now 
	FROM
		dual;
-- 查看重复数据
	SELECT
		sum( count( * ) ) INTO row1 
	FROM
		EVAL_SUM_NEWEST_INFO 
	GROUP BY
		eval_basic_information_id,
		eval_sum_risk_info_id,
		risk_dept_id 
	HAVING
		count( * ) > 1;
	IF
		( row1 > 0 ) THEN-- 如果存在重复数据,则删除存在的备份表(7天),创建新的备份表
			DAILY_BACKUP ( );
		BEGIN-- 查询 备份表 是否和 原表一致(说明备份数据完整,可以处理重复数据了)
			
			dbms_output.put_line ( '创建的表: ' || v_table_name_1 || v_now );
			dbms_output.put_line ( 'SELECT count( * ) FROM ( SELECT * FROM EVAL_SUM_NEWEST_INFO MINUS SELECT * FROM ' || v_table_name_1 || v_now || ' ) t' );
			-- 把拼接的语句 作比较,然后把数量 赋值给row2 
			execute IMMEDIATE 'SELECT count( * ) FROM ( SELECT * FROM EVAL_SUM_NEWEST_INFO MINUS SELECT * FROM ' || v_table_name_1 || v_now || ' ) t' INTO row2;
			
			IF
				( row2 > 0 ) THEN-- 这里是不一致(不做清理数据)
					
					dbms_output.put_line ( '00000000000' );
				
				ELSE dbms_output.put_line ( '11111111111' );
				
				-- 删除重复数据
				execute IMMEDIATE 'delete  EVAL_SUM_NEWEST_INFO WHERE id in  
				(
				select id from (
				select t.*, row_number() over(partition by eval_basic_information_id,eval_sum_risk_info_id,risk_dept_id order by id ) rn from EVAL_SUM_NEWEST_INFO t 
				) where rn > 1
				)';
				
			END IF;
			COMMIT;
			EXCEPTION 
				WHEN others THEN
				record_proc_err_log ( 'process', 'data', SQLCODE, SQLERRM, substr( dbms_utility.format_error_backtrace, 1, 400 ) );
			ROLLBACK;
			
		END;
		
	END IF;
END;

4. 创建定时任务 执行存储过程;

-- 1.创建任务
declare duplicate_data_job number;  --duplicate_data_job定时任务名称

begin

sys.dbms_job.submit(

duplicate_data_job, --任务名称

'PROCESS_DUPLICATE_DATA;',--执行的存储过程

sysdate,--执行时间

--'TRUNC(SYSDATE + 1) + (15*60+52)/(24*60)'--下次执行时间 11:55
'TRUNC(SYSDATE + 1)'  --每天午夜12点
--'sysdate+2/(24*60)'   --每2分钟执行一次

);

COMMIT;

end;

5. 查看任务的一些sql 命令(不需要执行,即参考);


-- 以下不需要执行,一些sql做参考 的查看命令


-- 查看定时任务
SELECT * FROM user_jobs;

-- 手动启动,执行完后再执行3 查看,如果next_date 没有自动变成明天这个时间的话,那么就需要配置下5 
BEGIN

dbms_job.run(25);

END;

-- ********* 
--在 90上试验之后是可以的 (通过查阅资料发现原来有一个参数job_queue_processes数字为0是定时任务都不会执行)
alter system set job_queue_processes =10;
-- ********* 



-- 删除存储过程
DROP PROCEDURE PROCESS_DUPLICATE_DATA;


-- 停止任务
BEGIN

dbms_job.broken(25,true);

END;


-- 删除任务
begin

dbms_job.remove(45);--ALL_JOBS.job的值

end;

三、嵌套begin end 里面 begin

-- 1.创建表 参数:表名,建表语句
CREATE 
	OR REPLACE PROCEDURE PROCESS_DUPLICATE_DATA2 IS row1 NUMBER;
row2 NUMBER;
BEGIN
	SELECT
		count( table_name ) INTO row1 
	FROM
		all_tables 
	WHERE
		table_name = upper( 'eval_sum_newest_info_bak' );
	IF
		( row1 = 1 ) THEN-- 删除存在的备份表,创建新的备份表
--execute immediate 'drop table EVAL_SUM_NEWEST_INFO_BAK';
--execute immediate 'create table eval_sum_newest_info_bak as select * from eval_sum_newest_info';
			dbms_output.put_line ( '00000000000' );
		BEGIN
			SELECT
				count( * ) INTO row2 
			FROM
				( SELECT * FROM EVAL_SUM_NEWEST_INFO MINUS SELECT * FROM EVAL_SUM_NEWEST_INFO_BAK ) t;
			IF
				( row2 > 0 ) THEN
					dbms_output.put_line ( '11111111111' );
				ELSE dbms_output.put_line ( '222222222222' );
				
			END IF;
			
		END;
		ELSE dbms_output.put_line ( '33333333333' );
		
	END IF;
END;

四、多个begin end 并行

CREATE 
	OR REPLACE PROCEDURE test IS row1 NUMBER;--第一个游标
row2 NUMBER;--第二个游标
BEGIN
BEGIN
	SELECT
		count( table_name ) INTO row1 
	FROM
		all_tables 
	WHERE
		table_name = upper( 'eval_sum_newest_info_bak' );
	IF
		( row1 = 1 ) THEN-- 删除存在的备份表,创建新的备份表
--execute immediate 'drop table EVAL_SUM_NEWEST_INFO_BAK';
--execute immediate 'create table eval_sum_newest_info_bak as select * from eval_sum_newest_info';
			dbms_output.put_line ( '0000000000' );
		ELSE dbms_output.put_line ( '33333333333' );
		
	END IF;
	
END;


--分开
BEGIN
SELECT
	count( * ) INTO row2 
FROM
	( SELECT * FROM EVAL_SUM_NEWEST_INFO MINUS SELECT * FROM EVAL_SUM_NEWEST_INFO_BAK ) t;
IF
	( row2 > 0 ) THEN
		dbms_output.put_line ( '11111111111' );
		ELSE dbms_output.put_line ( '222222222222' );
		
	END IF;
END;

END;
  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值