转:oracle触发器存储过程实践

最近项目中需要做一个数据同步功能,就是要将一个数据库里面的信息定时的同步到另外一个数据库中,这样的话就需要用到储存过程 触发器 定时器 和dblink.

以前没写过储存过程,恰好利用这次机会练练手,特写此博客,方便以后查阅:


序号 对象名称 类型 说明
1 synBaseDataTemp table 临时表
2 synBaseDataHistory table 同步历史记录
3 synBaseDataTemp_Sequence SEQUENCE 设置字段ID自增
4 tri_synBaseDataTemp TRIGGER 当临时表中有新增记录时,ID自动增加1
5 tri_基础数据表名 TRIGGER 当CCS基础数据表有增 删 改操作时,会自动触发在ECCS基础数据
表增加记录(共32个)
6 baseDataSynProc procedure 将临时表中记录的信息同步到ECCS中,同时将同步记录
增加到synBaseDataHistory中,并将同步的synBaseDataTemp信息删除

创建同步相关表:


[sql] view plaincopy

/*创建表synBaseDataTemp*/
CREATE TABLE synBaseDataTemp
(
id number(15,0) NOT NULL,
condition varchar2(300) not null,
tableName varchar2(40) not null,
operateType varchar2(20) not null,
operateDate date,
failFlag varchar2(1),
failTimes integer,
PRIMARY KEY (id)
);
comment on table synBaseDataTemp is '同步临时表';
comment on column synBaseDataTemp.id is '自增列,主键';
comment on column synBaseDataTemp.condition is '表主键条件';
comment on column synBaseDataTemp.tableName is '表名';
comment on column synBaseDataTemp.operateType is '操作类型';
comment on column synBaseDataTemp.operateDate is '操作时间';
comment on column synBaseDataTemp.failFlag is '失败标志,1失败';
comment on column synBaseDataTemp.failTimes is '失败次数';

/*创建表synHistory*/
CREATE TABLE synBaseDataHistory
(
id number(15,0) NOT NULL,
condition varchar2(300) not null,
tableName varchar2(40) not null,
operateType varchar2(20) not null,
operateDate date,
PRIMARY KEY (id)
);
comment on table synBaseDataHistory is '同步历史记录表';
comment on column synBaseDataHistory.id is '自增列,主键';
comment on column synBaseDataHistory.condition is '表主键条件';
comment on column synBaseDataHistory.tableName is '表名';
comment on column synBaseDataHistory.operateType is '操作类型';
comment on column synBaseDataHistory.operateDate is '操作时间';

/*为表synBaseDataTemp的ID创建自增列*/
--创建自动增长序列
CREATE SEQUENCE synBaseDataTemp_Sequence
INCREMENT BY 1
START WITH 1
NOMAXVALUE
NOCYCLE
CACHE 10;
--创建触发器
CREATE OR REPLACE TRIGGER tri_synBaseDataTemp BEFORE
insert ON synBaseDataTemp FOR EACH ROW
begin
select synBaseDataTemp_Sequence.nextval into:New.id from dual;
end;






为每张表创建触发器,共32张表,以一张表作为实例:
[sql] view plaincopy

</pre><p> </p><pre class="sql" name="code">/*为表GGSYSTEM创建触发器,当有相关操作时,在synBaseDataTemp中存入相关信息*/
CREATE OR REPLACE TRIGGER tri_GGSYSTEM
AFTER INSERT or DELETE or UPDATE --指定触发时机触发
ON GGSYSTEM
REFERENCING NEW as new_value
FOR EACH ROW --说明创建的是行级触发器
BEGIN
--将修改前数据插入到临时表synBaseDataTemp,供存储过程调用。
if inserting then
INSERT INTO synBaseDataTemp
(condition, tableName, operateType, operateDate)
VALUES
('SYSTEMCODE=' || chr(39) || :new_value.systemCode || chr(39),
'GGSYSTEM',
'INSERT',
sysdate);

elsif updating then
INSERT INTO synBaseDataTemp
(condition, tableName, operateType, operateDate)
VALUES
('SYSTEMCODE=' || chr(39) || :new_value.systemCode || chr(39),
'GGSYSTEM',
'UPDATE',
sysdate);

elsif deleting then
INSERT INTO synBaseDataTemp
(condition, tableName, operateType, operateDate)
VALUES
('SYSTEMCODE=' || chr(39) || :old.systemCode || chr(39),
'GGSYSTEM',
'DELETE',
sysdate);
end if;
END;




创建触发器后,下面是存储过程:


[sql] view plaincopy

--包头
create or replace package baseDataSyn is
-- Author : zhengfazhen
-- Created : 2011-12-31

procedure baseDataSynProc; --从CCS同步到ECCS

end baseDataSyn;



--包体
CREATE OR REPLACE PACKAGE BODY baseDataSyn is
-- Author : zhengfazhen
-- Created : 2011-12-31

--同步 存储过程
PROCEDURE baseDataSynProc IS
v_id number(15, 0); --临时表ID
condition varchar2(400); --临时表主键条件
tableName varchar2(50); --临时表中存入的表名
operateType varchar2(10); --操作类型:insert update delete
insertSql varchar2(400); --插入sql
updateSql varchar2(2000); --更新sql
deleteSql varchar2(500); --删除sql
synLogSql varchar2(500); --历史记录sql
columStr varchar2(1000); --非主键列名字符串
gguserColum varchar2(500); --GGUSER非主键且除去(password,PASSWORDSETDATE,PASSWORDEXPIREDATE,LOCKSTATUS,UPDATEPWDIND,LOGINERRTIMES)字段
gguserSql varchar2(500); --为gguser赋值默认值SQL
failSql varchar2(500); --异常处理SQL
flag varchar2(1);

--查询临时表中所有记录
cursor c_synTemp is
select c.id, c.condition, c.tablename, c.operatetype, c.operatedate
from synBaseDataTemp c
where 1 = 1
order by operateDate ASC;
c_synTemp_row c_synTemp%rowtype;

--返回非主键列名
cursor c_columName(tableName varchar2) is
select uc.COLUMN_NAME
from user_tab_columns uc
where uc.COLUMN_NAME not in
(select col.column_name
from user_constraints con, user_cons_columns col
where con.constraint_name = col.constraint_name
and con.constraint_type = 'P'
and col.table_name = tableName)
and uc.TABLE_NAME = tableName;
c_row c_columName%rowtype;

BEGIN
for c_synTemp_row in c_synTemp loop
begin
v_id := c_synTemp_row.id;
condition := c_synTemp_row.condition;
tableName := c_synTemp_row.tableName;
operateType := c_synTemp_row.operateType;

flag := '1';
/*拼接返回的非主键列名start*/
for c_row in c_columName(tableName) loop
if flag = '1' then
columStr := c_row.COLUMN_NAME;
flag := '0';
else
columStr := columStr || ',' || c_row.COLUMN_NAME;
end if;
end loop;
/*拼接返回的非主键列名end*/
/*同义词 eccs_表名*/
insertSql := 'insert into eccs_' || tableName ||
' (select * from ' || tableName || ' where ' ||
condition || ')';
updateSql := 'update eccs_' || tableName || ' set
(' || columStr || ')=(select ' || columStr ||
' from ' || tableName || ' where ' || condition ||
') where ' || condition;
deleteSql := 'delete from eccs_' || tableName || ' where ' ||
condition;
synLogSql := 'insert into synBaseDataHistory (select st.id,st.condition,st.tablename,st.operatetype,st.operatedate from synBaseDataTemp st where id=:1)';
failSql := 'update synBaseDataTemp set failFlag=' || chr(39) || '1' ||
chr(39) || 'where id=' || v_id;

/*GGUSER表特殊处理*/
gguserSql := 'update eccs_' || tableName ||
' set LOCKSTATUS=' || chr(39) || '1' || chr(39) ||
', UPDATEPWDIND=' || chr(39) || '1' || chr(39) ||
', LOGINERRTIMES=' || chr(39) || '0' || chr(39) ||
' where ' || condition;
gguserColum := 'USERCNAME,USERTNAME,USERENAME,SEAL,COMPANYCODE,ISSUECOMPANY,ACCOUNTCODE,PHONE,MOBILE,' ||
'ADDRESS,POSTCODE,EMAIL,USERIND,LOGINSYSTEM,CREATORCODE,CREATETIME,UPDATERCODE,' ||
'UPDATETIME,VALIDIND,REMARK,FLAG,SEX,ALIASCNAME,ALIASTNAME,ALIASENAME,UWINITIAL';

if tableName = 'GGUSER' then
updateSql := 'update eccs_' || tableName ||
' set
(' || gguserColum ||
')=(select ' || gguserColum || ' from ' || tableName ||
' where ' || condition || ') where ' || condition;
end if;

if operateType = 'INSERT' then
EXECUTE IMMEDIATE insertSql; --同步数据
if tableName = 'GGUSER' then
EXECUTE IMMEDIATE gguserSql; --赋默认值
end if;
EXECUTE IMMEDIATE synLogSql
USING v_id; --插入历史记录表
delete from synBaseDataTemp where id = v_id; --删除临时表中的信息
commit;
elsif operateType = 'UPDATE' then
EXECUTE IMMEDIATE updateSql;
EXECUTE IMMEDIATE synLogSql
USING v_id;
delete from synBaseDataTemp where id = v_id;
commit;
elsif operateType = 'DELETE' then
EXECUTE IMMEDIATE deleteSql;
EXECUTE IMMEDIATE synLogSql
USING v_id;
delete from synBaseDataTemp where id = v_id;
commit;
end if;
exception when others then
rollback;
EXECUTE IMMEDIATE failSql;--更新异常标志
commit;
end;
end loop;
END baseDataSynProc;

end baseDataSyn;


创建job,定时执行储存过程:


[sql] view plaincopy

BEGIN
DBMS_SCHEDULER.CREATE_JOB(job_name => 'jobsynproc', --job名称,自己设
job_type => 'STORED_PROCEDURE', --类型为存储过程
job_action => 'ccs_synproc', --存储过程名称为proc
start_date => to_date('30-12-2011 00:00:00',
'dd-mm-yyyy hh24:mi:ss'), --开始执行时间
enabled => TRUE, --自动启用
auto_drop => false,
repeat_interval => 'FREQ=Monthly;Interval=1');
END;


在这之前,必须授权用户有增删改的权限,并且创建同义词,以便储存过程能顺利执行:



1.依照DBA用户登录执行sql命令:grant create synonym to 被授权用户;
2.如果你需要对某表可以修改等权限:需执行:grant select,insert,update on monitor_sys_log to 被授权用户;

3.用"被授权用户"登录创建同义词:create synonym monitor_sys_log(同义词名称) for 拥有表用户.monitor_sys_log(表名);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值