明天的明天 永远的永远 未知的一切 我与你一起承担 ??

是非成败转头空 青山依旧在 几度夕阳红 。。。
随笔 - 1277, 文章 - 0, 评论 - 214, 阅读 - 321万
  博客园  :: 首页  :: 管理
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

迁移数据到历史表SQL .

Posted on   且行且思  阅读(1732)  评论(0编辑  收藏  举报

有时工作需要需要把当前表的数据,移到历史表中,而历史表基本是以时间(年)为后缀来命名历史表的,如 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
复制代码

 

编辑推荐:
· 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的实现方案
点击右上角即可分享
微信分享提示