|
有时候我们可能需要某个数据库的个别表,但同步数据往往会遇到一些问题。例如,由于权限问题无法发布订阅远程数据库。这时候链接服务器几乎成为不二选择了。但全量更新通常也会遇到一些问题,例如,当数据超过1000万行的时候。
最初我的思路是每天只更新不一样的数据。当时打算通过主键来匹配,新增的就更新,原表不存在的则删除。后来发现,还存在更改的很难判断。主键不变,如果每个字段去检查是否变更,相当繁琐。
所以打算不再同步数据表,而改为将所需基础数据追加到本地。如此一来,将不必更新多个表,而改为若干个字段就足矣。
在实际操作过程中,一开始是打算按查询的思路来完成,把所需的表进行整合,一次性把所需数据提取出来,发现需要运行很久。于是决定拆开多个查询,单表追加基础数据后,再逐步更新,应该会好些。
经测试,查询数据是比较快的,但追加到本地表则很慢,即便只有几万行。因此开始怀疑可能是运行脚本时需要调用大量资源,便思考是否可以考虑临时表来处理。于是就有了以下脚本:
- CREATE PROCEDURE [dbo].[A9_Sametime](@startDate date = null) as
- if @startDate is null
- set @startDate=GETDATE()
- declare
- --长日期
- @startDateTime datetime,
- @firstDayDateTime datetime,
- @endDateTime datetime,
- @sql1 varchar(8000),
- @sql2 varchar(1000),
- @sql3 varchar(1000)
- set @startDateTime=DATEADD(day,-1,@startDate)
- set @firstDayDateTime=DATEADD(day,1-day(@startDate),@startDate)
- set @endDateTime=DATEADD(MILLISECOND,-3,convert(datetime,@startdate))
- --追加前一天数据
- set @sql1 = 'select * into ##temp from openquery(A9Server, ''select CustomerID 客服ID,SalesStaff 工号,max(StartTime) 最近接通日期,'
- +' CONVERT(VARCHAR(8),DATEADD(ss,sum(BillableSeconds),''''1900-01-01 00:00:00''''),108) as 通话时长,'
- +' count(SalesStaff) 通话次数, sum(case when BillableSeconds>=1 then 1 else 0 end) 接通次数,'
- +' Destination 外呼号码 from [A9SERVER].[S60623].[dbo].[bmdcallcenterrecord] '
- +' where StartTime between '''''+convert(varchar(23),@startDateTime,21)+''''' and '''''
- +convert(varchar(23),@endDateTime,21)+''''' group by CustomerID,SalesStaff,Destination'')'
- --更新订单号信息
- set @sql2 = 'select * into ##temp from openquery(A9Server,''select a.CustomerID,a.ID,a.LastFollowDate,'
- +' a.LastFollowContent,cs.CommunicateStatus from [A9SERVER].[S60623].[dbo].[bdCustomerAllocate] a,'
- +' [A9SERVER].[S60623].[dbo].[mdcommunicatestatus] cs where len(a.LastCommunicateStatus)>0 '
- +' and LastFollowDate between '''''+convert(varchar(23),@startDateTime,21)+''''' and '''''
- +convert(varchar(23),@endDateTime,21)+''''' and a.LastCommunicateStatus=convert(varchar(50),cs.ID)'')'
- --更新提醒信息
- set @sql3 = 'select * into ##temp from openquery(A9Server,'
- +' ''select u.UserName,d.DepartName,u.WorkNo from [A9SERVER].[S60623].[dbo].[frmuser] u,'
- +' [A9SERVER].[S60623].[dbo].[mdDepartment] d where u.DepartmentID=d.id'')'
- BEGIN
- --set nocount on
- --set nocount off
- exec(@sql1)
- insert into tblWidth(客户ID,工号,最近接通日期, 通话时长,通话次数,接通次数,外呼号码)
- select * from ##temp
- if exists (select * from tempdb.dbo.sysobjects where id = object_id(N'tempdb..##temp') and type='U')
- drop table ##temp
- --
- exec(@sql2)
- update tblWidth set 分配ID=s.ID,最后沟通时间=s.LastFollowDate,沟通结果=s.LastFollowContent,
- 沟通状态=s.CommunicateStatus from ##temp s where
- s.CustomerID=tblWidth.客户ID and tblWidth.分配ID is null
- if exists (select * from tempdb.dbo.sysobjects where id = object_id(N'tempdb..##temp') and type='U')
- drop table ##temp
- exec(@sql3)
- update tblWidth set 客服=UserName,部门=DepartName from ##temp s
- where s.WorkNo=工号 and 客服 is null
- if exists (select * from tempdb.dbo.sysobjects where id = object_id(N'tempdb..##temp') and type='U')
- drop table ##temp
- END
复制代码 值得注意的是,双井号(##)才可以多次使用。用单井号(#)则运行完第一个语句后,临时表将消失(即第二个语句将出现错误)。拼接SQL语句比较麻烦,但考虑到需要按日期来执行语句,而且涉及到链接服务器(openquery),那也是必不可免的事情了。在拼接过程中,大家需要注意单引号的使用。
|
|