发布同表结构的数据同步存储过程!欢迎拍砖!

zhangqu_980371 2006-05-15 06:29:49
/*
近日无事,写了一存储过程实现A,B同结构表的数据同步的简单处理的存储过程,欢迎大家丢砖.
基本功能为同步insert AB的记录,最后以AB其中一表为准更新另外一表的差异记录.

1.对于关键或者有些列为自增类型的,应该预先处理掉,这里留代各位大侠以后处理,好像是先建立一个去掉自增属性的临时表,
然后导入原表数据,删除原表,再重新命表名
2.对应是否需要关闭触发器,也未作处理.可以添加一个参数进行指示是否关闭触发器
3.应考虑外键和约束.
4.如AB表结构不一致的复杂度将大为增加,(实用性也将大大提高)
呵呵,所以复杂的还是要考虑很多因素,不能简单的insert update了事.

主要过程:
1.从syscolumns,sysobjects,sysindexkeys表中获取表的字段信息
2.构造insert同步语句
3.构造update同步语句

欢迎指出错误及纠正.
*/
CREATE Procedure tb_tab(@tab1 varchar(50),@tab2 varchar(50),@itab int)
/*
@tab1--A表表名
@tab2--B表表名
@itab--2:以B的数据更新A表
<>2:以A的数据更新B表
*/
as
declare @sql varchar(2000);
declare @sql_temp varchar(1000);
declare @field_name varchar(50);
declare @tabupdateto varchar(50);
declare @tabupdatefrom varchar(50);

--声明全部列,不用
--declare cur_field1 cursor for
--select syscolumns.name from syscolumns,sysobjects where syscolumns.id = sysobjects.id and sysobjects.name = @tb;
/*
在游标声明中无法使用变量,所以将游标要使用的变量先保存到临时表.实在没办法啦:).嘻嘻,可能我不知道别的办法.
*/
select @tab1 as c_tbn into #tbtmp;

--声明关键字列游标
declare cur_key1 cursor for select syscolumns.name from syscolumns,sysobjects,sysindexkeys,#tbtmp where syscolumns.id = sysobjects.id and sysobjects.name = #tbtmp.c_tbn
and sysobjects.id = sysindexkeys.id and sysindexkeys.colid = syscolumns.colid and sysindexkeys.indid = 1;

--声明关普通列游标
declare cur_notkey_field cursor for select syscolumns.name from syscolumns,sysobjects,#tbtmp where syscolumns.id = sysobjects.id and sysobjects.name = #tbtmp.c_tbn
and not exists (select * from sysindexkeys where sysobjects.id = sysindexkeys.id and sysindexkeys.colid = syscolumns.colid and sysindexkeys.indid = 1);

/*
insert into test1(*) select * from test2 where not exits (select * from test1 where test1.c_col1 = test2.c_col1 and test1.c_col2 = test2.c_col2)
select test2.* from test2 where not EXISTS ( select * from test1 where test2.c_col1 = test1.c_col1 and test2.c_col2 = test1.c_col2)
*/

begin
/*

插入A表在B表中没有的数据
--insert test1 select * from test2 where not EXISTS ( select * from test1 where test2.c_col1 = test1.c_col1 and test2.c_col2 = test1.c_col2)
*/
select @sql = 'insert into ' + @tab1 +' select * from ' + @tab2 + ' where not EXISTS ( select * from ' + @tab1 + ' where ';
select @sql_temp = '';
open cur_key1;
--PRINT @@ERROR
FETCH NEXT FROM cur_key1 into @field_name;
--PRINT @field_name;
--PRINT @@FETCH_STATUS
while @@FETCH_STATUS = 0
begin
if @sql_temp <> ''
begin
select @sql_temp = @sql_temp + ' and ';
end
select @sql_temp = @sql_temp + @tab1 + '.' + @field_name + ' = ' + @tab2 + '.' + @field_name ;

fetch next from cur_key1 into @field_name;
end

select @sql_temp = @sql_temp + ')';
select @sql = @sql + @sql_temp;
close cur_key1;
EXEC(@sql);
--PRINT @@ERROR

/*
插入B表在A表中没有的数据
--insert test2 select * from test1 where not EXISTS ( select * from test2 where test2.c_col1 = test1.c_col1 and test2.c_col2 = test1.c_col2)
*/
select @sql = 'insert into ' + @tab2 +' select * from ' + @tab1 + ' where not EXISTS ( select * from ' + @tab2 + ' where ';
select @sql_temp = '';
open cur_key1;
fetch next from cur_key1 into @field_name;

while @@FETCH_STATUS = 0
begin
if @sql_temp <> ''
begin
select @sql_temp = @sql_temp + ' and ';
end
select @sql_temp = @sql_temp + @tab2 + '.' + @field_name + ' = ' + @tab1 + '.' + @field_name ;
fetch next from cur_key1 into @field_name;
end

select @sql_temp = @sql_temp + ')';
select @sql = @sql + @sql_temp;
close cur_key1;
exec(@sql);

/*
以指定表的数据为准,更新另外一个表的数据
update test2 set test2.d_date = test1.d_date , test2.f_number = test1.f_number
from test1 where test2.c_col1 = test1.c_col1 and test2.c_col2 = test1.c_col2
and ((test2.d_date <> test1.d_date or test1.d_date is null) or (test2.f_number <> test1.f_number or test1.f_number is null))
*/
select @tabupdatefrom = @tab1;
select @tabupdateto = @tab2;
if @itab = 2
begin
select @tabupdatefrom = @tab2;
select @tabupdateto = @tab1;
end

select @sql = 'update ' + @tabupdateto + ' set ';
select @sql_temp = '(';
open cur_notkey_field;
fetch next from cur_notkey_field into @field_name;

while @@FETCH_STATUS=0
begin
if @sql_temp <> '('
begin
select @sql_temp = @sql_temp + ' or (' + @tabupdateto + '.' + @field_name + ' <> ' + @tabupdatefrom + '.' + @field_name + ' or ' + @tabupdatefrom + '.' + @field_name + ' is null or ' + @tabupdateto + '.' + @field_name + ' is null) ';
end
else
begin
select @sql_temp = @sql_temp + ' (' + @tabupdateto + '.' + @field_name + ' <> ' + @tabupdatefrom + '.' + @field_name + ' or ' + @tabupdatefrom + '.' + @field_name + ' is null or ' + @tabupdateto + '.' + @field_name + ' is null) ';
end

if @sql <> 'update ' + @tabupdateto + ' set '
begin
select @sql = @sql + ' , '+ @tabupdateto + '.' + @field_name + ' = ' + @tabupdatefrom + '.' + @field_name;
end
else
begin
select @sql = @sql + @tabupdateto + '.' + @field_name + ' = ' + @tabupdatefrom + '.' + @field_name;
end

fetch next from cur_notkey_field into @field_name;
end
close cur_notkey_field;
deallocate cur_notkey_field;
select @sql = @sql + ' from ' + @tabupdatefrom+ ' where ' + @sql_temp + ') and ';
select @sql_temp = '( ';

open cur_key1;
fetch next from cur_key1 into @field_name;

while @@FETCH_STATUS = 0
begin
if @sql_temp <> '( '
begin
select @sql_temp = @sql_temp + ' and ';
end
select @sql_temp = @sql_temp + @tab2 + '.' + @field_name + ' = ' + @tab1 + '.' + @field_name;
fetch next from cur_key1 into @field_name;
end

select @sql_temp = @sql_temp + ')';
select @sql = @sql + @sql_temp;
close cur_key1;
deallocate cur_key1;
exec(@sql);
--print @sql
drop table #tbtmp;
end
...全文
354 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
rookie_one 2007-02-08
  • 打赏
  • 举报
回复
说得好啊!
大师的话真如“大音希声扫阴翳”,犹如“拨开云雾见青天”,使我等网民看到了希望,看到了未 来!晴天霹雳、醍醐灌顶或许不足以形容大师文章的万一;巫山行云、长江流水更难以比拟大师的文才!黄钟大吕 ,振聋发聩!你烛照天下,明见**;雨露苍生,泽被万方!透过你深邃的文字,我仿佛看到了你鹰视狼顾、龙行 虎步的伟岸英姿;仿佛看到了你手执如椽大笔、写天下文章的智慧神态;仿佛看见了你按剑四顾、指点江山的英武 气概!
OracleRoob 2007-02-08
  • 打赏
  • 举报
回复
对于自动编号字段,用如下语句处理:

SET IDENTITY_INSERT
允许将显式值插入表的标识列中。


SET IDENTITY_INSERT 表名 ON


SET IDENTITY_INSERT 表名 OFF
ldw701 2007-02-08
  • 打赏
  • 举报
回复
mark
zhf777 2006-05-30
  • 打赏
  • 举报
回复
mark一下
最近在搞两个数据库的远程同步
用SQL的复制功能达不到增量实时快速的要求
有时间测试一下楼主的存储过程
3Q
wwh999 2006-05-18
  • 打赏
  • 举报
回复
Mark :) 这么长...研究一下
lovcal 2006-05-15
  • 打赏
  • 举报
回复
有时间研究一下……
niulity 2006-05-15
  • 打赏
  • 举报
回复
8错,但如果A与B不在同一服务器上呢,这种情况才是真正需要同步的 ^_^
muleo 2006-05-15
  • 打赏
  • 举报
回复
mark
itblog 2006-05-15
  • 打赏
  • 举报
回复
sf

34,575

社区成员

发帖
与我相关
我的任务
社区描述
MS-SQL Server相关内容讨论专区
社区管理员
  • 基础类社区
  • 二月十六
  • 卖水果的net
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧