日期:2014-05-18 浏览次数:20457 次
insert tb select * from( select * from tb1 union select * from tb2 union select * from tb3 )t --删除重复行: delete a from tb a where exists (select 1 from tb b where a.col=b.col and a.id<b.id)
------解决方案--------------------
TravyLee确实实战经验丰富啊,赞一个。
但是个人感觉先插入,再删除的做法,在效率上稍欠,无论是sql server还是oracle,都提供了merge的语法,使用系统自带的东西,个人感觉总比自己操作要好。
嗯,还有点小毛病是最终合并出来的表,如果采用自动增长列,删除数据后,编号无法保证连续。当然,对用没有任何影响,只是对于某些偏执狂而言。
下面提供了段代码,用了游标,个人是不喜欢用游标的,影响效率,但对于这种数据量不大的表,倒也不是太大的问题。
如果说到有更好的解决办法,我觉得是不用存储过程,直接使用osql生成sql脚本,原理和上面TravyLee所说的类似(oracle中常用的手法)。
然后再在调度中,每月定时执行,可能会更好些。
该吃饭了,去晚了就没了,脚本的办法一会再说。
以上,如果说得不对,请各位指正。
--测试数据,待合并表; create table a_s1( id int ); go create table a_s2( id int ); go create table a_s3( id int ); go --测试数据; insert a_s1 select 1 union all select 2; go insert a_s2 select 2 union all select 3; go insert a_s3 select 3 union all select 4 union all select 5 go select * from a_s1; select * from a_s2; select * from a_s3; --临时表,合并数据至此表; create table #tt ( id int identity(1,1), value int ) go select * from #tt; --开始创建存储过程; if OBJECT_ID('pro_test') is not null begin drop proc pro_test; end; go --创建存储过程; CREATE PROC pro_test AS BEGIN --声明变量,存放待执行动态sql语句; DECLARE @sql varchar(max); --声明变量,用于存放表名; DECLARE @tableName varchar(max); --声明游标,用于读取表名; DECLARE myCursor CURSOR FOR SELECT name FROM sysobjects WHERE xtype='U' and category=0 and CHARINDEX('a_',name)=1; --打开游标 OPEN myCursor; --开始读取; FETCH NEXT FROM myCursor INTO @tableName; WHILE @@FETCH_STATUS = 0 BEGIN --PRINT @tableName; --动态创建sql语句; set @sql = 'MERGE INTO #tt AS t ' + ' using (select id from ' + @tableName + ') as s ' + ' on t.id = s.id ' + ' when not matched then ' + ' insert (value) values (id);'; --print @sql; --执行; exec(@sql); FETCH NEXT FROM myCursor INTO @tableName; END; --关闭游标; CLOSE myCursor; DEALLOCATE myCursor; END; pro_test; --查看数据 select * from #tt;