oracle数据库表部分字段双向同步,利用包和触发器实现

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

oracle数据库表部分字段双向同步,利⽤包和触发器实现
需求:数据库⾥⾯有两张表,结构不完全相同,需要实时同步两张表的部分字段
实现⽅案:两张表上分别建⽴触发器进⾏同步,但是这样操作会有个问题,就会导致触发器循环触发。

那么就需要在触发器进⾏触发前,进⾏⼀个判断,如果操作是由触发器引发的,那么就不做操作,反之,执⾏触发器定义的操作。

想要实现这个,我开始考虑过在触发器a⾥⾯暂时使触发器b失效,但是发现alter trigger disable不合法;然后看到有⼈提到在表⾥⾯新增⼀个字段,⽤来做标识,但是这样需要修改表结构,虽然可以达到要求,但是总觉得不是很好,所以也没有使⽤;后来通过学习oracle对象,了解到了包的特性,所以决定采⽤包的⽅式来实现,利⽤包的变量来做标识。

/*操作过程中,需要分别执⾏‘包’,‘函数’,‘触发器’;⼀次性执⾏会有问题
操作完成后,注意检查‘包’,‘函数’,‘触发器’状态是否有效*/
--创建包头
create or replace package pk_check_active is
--标识是否为触发器引发
n number :=0;
 --获取是否我触发器触发标识,1为触发器触发
function getactive return number;
--设置状态
procedure setactive(n1 in number);
end pk_check_active;
/*这⾥的/⼀定不能缺少*/
/
create or replace package body pk_check_active as
function getactive return number is
begin
return n;
end getactive;
procedure setactive(n1 in number) is
begin
n := n1;
end setactive;
end pk_check_active;
--获取guid的⽅式,采⽤了8-4-4-4-12的格式
create or replace function Creategs_oid return varchar2
is
guid varchar(64);
result varchar(64);
begin
guid := sys_guid();
result := substr(guid,1,8)||'-'||substr(guid,9,4)||'-'||
substr(guid,13,4)||'-'||substr(guid,17,4)||'-'||substr(guid,21,12);
return (result);
end Creategs_oid;
--触发表tableA
create or replace trigger tr_cs_user after insert or update or delete
on tableA for each row
begin
if pk_check_active.getactive() =1then
pk_check_active.setactive(2); return;
else
pk_check_active.setactive(1);
end if;
if inserting then
insert into tableB (gs_oid,s_username,s_password) values (Creategs_oid(),:,:new.pass);
elsif updating then
update taableB t set t.s_username=: ,t.s_password=:new.pass where t.s_username=:;
elsif deleting then
delete from tableB t where t.s_username = :;
end if;
pk_check_active.setactive(0);
end;
--获取指定列最⼤值+1(也是⼀种id的标识⽅法,开始没有做成⾃增字段,所以写触发器的时候需要⾃⼰来实现了)
create or replace function GetCSUserID return number
is
result number;
begin
select max(userid)+1into result from tableA;
return (result);
end GetCSUserID;
--触发tableB
create or replace trigger tr_bs_user after insert or update or delete
on tableB for each row
begin
if pk_check_active.getactive() =1then
pk_check_active.setactive(2); return;
else
pk_check_active.setactive(1);
end if;
if inserting then
insert into tableA (userid,name,pass,version,useable,remark)
values (GetCSUserID(),:new.s_username,:new.s_password,'SDE.DEFAULT','0','⽤户⾃动添加');
elsif updating then
update tableA t set =:new.s_username, t.pass=:new.s_password where =:old.s_username;
elsif deleting then
delete from tableA t where = :old.s_username;
end if;
pk_check_active.setactive(0);
end;
上⾯的代码,涉及到了包,触发器,函数,存储过程。

通过这个⼩事例,可以了解到常⽤触发器的⽤法,同时还有格式化guid的⽅法,应该对⼤家还是有⼀些⽤处的。

这种⽅式,只能对同⼀个⽤户下的表进⾏同步,如果是跨⽤户的情况下,这种⽅式是⽆效的。

引⽤"由于package的全局变量在数据库层次上并不可见,所以每个session都可以认为是⼀个被实例化了的package对象。

在session级别上对全局变量执⾏的赋值操作并不会被其他session看到,很好地体现了数据的封装性。

"所以说,通过包的变量来控制,必须是在⼀个session 下。

按照我的理解,如果采⽤ado⽅式,那么⼀个连接就算是⼀个session。

那么有没有跨session的访问的⽅式呢,问了⼀下⾕歌,是有解决⽅式,不过我测试了没成功,就不卖弄了,在参考⽂章⾥⾯会提到。

参考内容:。

相关文档
最新文档