您现在的位置:软界网技术中心数据库Oracle > 技术显示
经验总结:SQL Server与Oracle的数据同步
2008-6-12 0:00:00   网友评论       阅读次数 点此评论
   

  这篇论坛文章主要介绍了SQL ServerOracle的数据同步方案及解决过程,更多内容请参考下文:

  说到同步,其实是靠'作业'定时调度存储过程来操作数据,增,删,改,全在里面,结合触发器,游标来实现,关于作业调度,我使用了5秒运行一次来实行'秒级作业',这样基本就算比较快的'同步'

  我做的是SQL Server往Oracle端同步,先在sql server上建立往Oracle端的链接服务器,我用一个视图'封装'了一下链接服务器下的一张表。

  create view v_ora_PUBLISHLASTREC

  as

  select * from ORACLEDB..ROADSMS.PUBLISHLASTREC

  //ORACLEDB链接服务器名,ROADSMS为表空间名,PUBLISHLASTREC 为数据表名

  然后我们分别在sql server 要同步的表上建立,insert,delete,update触发器

  脚本如下:

  --说明:modiid等于1为insert,2为delete,3为update

  create trigger trg_PUBLISHLASTREC_insert on PUBLISHLASTREC for insert

  as

  insert into dbo.PublishLastRec_SQL(modiid,SignalGUID,AreaNo,SignalNote,AreaNote,PublishRoadStatus,PublishTime,IsExec)

  select '1',SignalGUID,AreaNo,SignalNote,AreaNote,PublishRoadStatus,PublishTime,'0' from inserted

  create trigger trg_PUBLISHLASTREC_update on PUBLISHLASTREC for update

  as

  insert into dbo.PublishLastRec_SQL(modiid,SignalGUID,AreaNo,SignalNote,AreaNote,PublishRoadStatus,PublishTime,IsExec)

  select '3',SignalGUID,AreaNo,SignalNote,AreaNote,PublishRoadStatus,PublishTime,'0' from inserted

  create trigger trg_PUBLISHLASTREC_delete on PUBLISHLASTREC for delete

  as

  insert into dbo.PublishLastRec_SQL(modiid,SignalGUID,AreaNo,SignalNote,AreaNote,PublishRoadStatus,PublishTime,IsExec)

  select '2',SignalGUID,AreaNo,SignalNote,AreaNote,PublishRoadStatus,PublishTime,'0' from deleted

  所有的操作都是把各幻表的数据插入到一张表中,上面统一插入的表为PublishLastRec_SQL,记录下操作的标识,以标识该条记录是插入,删除,还是修改,modiid等于1为insert,2为delete,3为update,字段isexec标识该条记录是否已处理,0为未执行的,1为已执行的

  接着就是最关键的一步,存储过程

  脚本如下:

  ALTER proc pro_PublishLastRec_Sql

  as

  declare @modiid int

  declare @signalguid int

  declare @areano numeric(1,0)

  declare @signalnote varchar(50)

  declare @areanote varchar(50)

  declare @publishroadstatus varchar(20)

  declare @publishtime varchar(50)

  

  if not exists(select * from PublishLastRec_SQL where IsExec=0)

  begin

  truncate table PublishLastRec_SQL

  return

  end

  declare cur_sql cursor for

  select modiid,SignalGUID,AreaNo,SignalNote,AreaNote,PublishRoadStatus,PublishTime from

  PublishLastRec_SQL where IsExec=0 order by [id]--IsExec 0为未执行的,1为已执行的

  open cur_sql

  fetch next from cur_sql into @modiid,@SignalGUID,@AreaNo,@SignalNote,@AreaNote,@PublishRoadStatus,@PublishTime

  

  while @@fetch_status=0

  begin

  if (@modiid=1) --插入

  begin

  insert into v_ora_PUBLISHLASTREC(SignalGUID,AreaNo,SignalNote,AreaNote,PublishRoadStatus,PublishTime)

  values(@SignalGUID,@AreaNo,@SignalNote,@AreaNote,@PublishRoadStatus,@PublishTime)

  end

  if (@modiid=2) --删除

  begin

  delete from v_ora_PUBLISHLASTREC where SignalGUID=@SignalGUID and AreaNo=@AreaNo

  end

  if (@modiid=3) --修改

  begin

  update v_ora_PUBLISHLASTREC

  set SignalNote=@SignalNote,AreaNote=@AreaNote,PublishRoadStatus=@PublishRoadStatus,

  PublishTime=@PublishTime

  where SignalGUID=@SignalGUID and AreaNo=@AreaNo

  end

  update PublishLastRec_SQL

  set IsExec=1

  where current of cur_sql

  fetch next from cur_sql into @modiid,@SignalGUID,@AreaNo,@SignalNote,@AreaNote,@PublishRoadStatus,@PublishTime

  end

  deallocate cur_sql

  该存储过程使用游标逐行提取PublishLastRec_Sql记录,根据modiid判断不同的数据操作,该条记录处理完毕后把isexec字段更新为1.

  最后是调用该存储过程的作业,我们先建一个一分钟运行一次的作业,然后在'步骤'的脚本中这样写:

  DECLARE @dt datetime

  SET @dt = DATEADD(minute, -1, GETDATE())

  WHILE @dt < GETDATE()

  BEGIN

  EXEC pro_PublishLastRec_Sql --这里pro_PublishLastRec_Sql 为你要作业执行的存储过程

  WAITFOR DELAY '00:00:05' -- 等待5秒, 根据你的需要设置即可

  END

  现在,我们即可以实现5秒执行一次该存储过程,做到5秒数据同步。

  

 
      来源: 作者:
 
【评论查看】