日期:2014-05-18 浏览次数:20575 次
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;