有时工作需要需要把当前表的数据,移到历史表中,而历史表基本是以时间(年)为后缀来命名历史表的,如 A_2011,A_2012,在移数据时,要按数据的时间,移到不同的表中,且由于如果数据有同步。一次处理的数据不能太大。否则同步链会被Block.所以需要批理处理。
下面是一个通用的写法,可以作为参考!(这个应该是出自邹建大侠之手,因为需要写这样的处理,去找了下类似代码,找到的)
-- row batch: 100 -- row Process limit: 50000 -- data keep days: 90 -- */ CREATE PROCEDURE dbo.TransferNInvoiceToHistoryBeforeDay @FromDate char(10) AS SET NOCOUNT ON; -- current trancount DECLARE @__trancount int; SELECT @__trancount = @@TRANCOUNT; BEGIN TRY DECLARE @row_batch int, @row_limit int, @row_process int, @row_count int, @date_begin datetime, @date_end datetime; -- row batch and data keep date SELECT @row_batch = 100, -- each batch process rows @row_limit = 50000, -- total row process limit @date_end = @FromDate,--DATEDIFF(Day, 90, GETDATE()), -- process top date @row_process = 0; -- process rows total -- =========================================== -- get process begin date and rows SELECT @date_begin = MIN(InvoiceDate), @row_count = COUNT(*) FROM 需要处理的当前表名 WITH(NOLOCK) WHERE InvoiceDate < @date_end; IF @row_count = 0 RETURN; ELSE IF @date_begin IS NULL BEGIN RAISERROR(N'column InvoiceDate include NULL value, please fix it', 16, 1) END IF @row_limit IS NULL OR @row_limit <= 0 SET @row_limit = @row_count; RAISERROR('%d rows need process, current process limit %d rows', 10, 1, @row_count, @row_limit) WITH NOWAIT -- =========================================== -- process by year DECLARE @date datetime; SET @date = @date_begin; WHILE @row_process < @row_limit AND @date < @date_end BEGIN -- process date and sql DECLARE @sql nvarchar(4000), @_date_begin datetime, @_date_end datetime; SELECT @_date_begin = @date, @_date_end = CASE WHEN DATEDIFF(Year, @_date_begin, @date_end) = 0 THEN @date_end ELSE DATEADD(Year, YEAR(@_date_begin) - 1899, 0) END, @date = @_date_end, @row_count = @row_batch, @sql = N' DECLARE @tb_id TABLE( invoiceNumber int PRIMARY KEY ); INSERT @tb_id SELECT TOP(@row_batch) invoiceNumber FROM Nact.dbo.NewEgg_InvoiceMaster A WHERE InvoiceDate >= @_date_begin AND InvoiceDate < @_date_end; DELETE A OUTPUT deleted.* INTO 历史表名不带时间部份' + RTRIM(Year(@_date_begin)) + N' FROM 当前表名 A, @tb_id B WHERE A.invoiceNumber = B.invoiceNumber; '; -- =========================================== -- process by batch for year WHILE @row_process < @row_limit AND @row_count = @row_batch BEGIN -- move data IF @__trancount = 0 BEGIN TRAN; ELSE SAVE TRAN __TRAN_SavePoint; EXEC sys.sp_executesql @sql, N' @row_batch int, @_date_begin datetime, @_date_end datetime ', @row_batch, @_date_begin, @_date_end; SELECT @row_count = @@ROWCOUNT, @row_process = @row_process + @row_count; IF XACT_STATE() = 1 AND @__trancount = 0 COMMIT; END END IF @__trancount = 0 BEGIN IF XACT_STATE() = -1 ROLLBACK TRAN; ELSE BEGIN WHILE @@TRANCOUNT > 0 COMMIT TRAN; END END END TRY BEGIN CATCH IF XACT_STATE() <> 0 BEGIN IF @__trancount = 0 ROLLBACK TRAN; ELSE IF XACT_STATE() = 1 AND @@TRANCOUNT > @__trancount ROLLBACK TRAN __TRAN_SavePoint; END DECLARE @__error_number int, @__error_message nvarchar(2048), @__error_severity int, @__error_state int, @__error_line int, @__error_procedure nvarchar(126), @__user_name nvarchar(128), @__host_name nvarchar(128); SELECT @__error_number = ERROR_NUMBER(), @__error_message = ERROR_MESSAGE(), @__error_severity = ERROR_SEVERITY(), @__error_state = ERROR_STATE(), @__error_line = ERROR_LINE(), @__error_procedure = ERROR_PROCEDURE(), @__user_name = SUSER_SNAME(), @__host_name = HOST_NAME(); RAISERROR( N'User: %s, Host: %s, Procedure: %s, Error %d, Level %d, State %d, Line %d, Message: %s ', @__error_severity, 1, @__user_name, @__host_name, @__error_procedure, @__error_number, @__error_severity, @__error_state, @__error_line, @__error_message); END CATCH GO
分类:
SQL Server
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 因为Apifox不支持离线,我果断选择了Apipost!
· 通过 API 将Deepseek响应流式内容输出到前端
2007-11-23 ASP.NET地址重写、使用伪静态、页面回发处理
2007-11-23 Net2.0如何实现伪静态技术,或者地址重写?
2007-11-23 网站二级域名用asp.net 2.0的实现方案