T-SQL WHERE 循环中的 BEGIN TRANSACTION 和 COMMIT 在删除记录时失败

T-SQL BEGIN TRANSACTION and COMMIT within a WHERE Loop fails when deleting records

以下代码旨在按月循环并删除 t运行sactions。但是,它没有按照我预期的方式执行。我期待在每次 DELETE 之后发生 COMMIT。

例程在 运行 超出日志 space 并回滚它删除的 t运行 操作的 ALL 时失败。 COMMIT 没有按照我预期的方式执行。为了控制日志 space,我假设循环中的 COMMIT 每个月都会删除 COMMIT,因此,防止日志 space 过度填充。

DECLARE @MaxPostDate AS DATE = '2021-01-31'
DECLARE @MinPostDate AS DATE = '2019-07-01'

DECLARE @NbrOfMonthsToMaintain As INT = 13 

WHILE @NbrOfMonthsToBeDeleted >= 0
BEGIN 

    SELECT @NbrOfTransactions = COUNT(*) 
    FROM [dbo].[Transaction] f
    WHERE f.[PostDate] BETWEEN @StartingDeleteDate AND EOMONTH(@StartingDeleteDate)

    PRINT 'Delete ' + FORMAT(@NbrOfTransactions,'N0') + ' transactions between ' 
                    + CAST(@StartingDeleteDate As VARCHAR(20)) + ' AND ' 
                    + CAST(EOMONTH(@StartingDeleteDate) AS VARCHAR(20))
 
        BEGIN TRANSACTION

            DELETE f
            FROM [dbo].[Transaction] f
            WHERE f.[PostDate] BETWEEN @StartingDeleteDate AND EOMONTH(@StartingDeleteDate)
            AND f.[PostDate] <= @DeleteToDate

        COMMIT TRANSACTION

        INSERT INTO [app].[DataDeletionHistory](
             [DataType] 
            ,[Description]
            ,[DateDeleted]
            ,[MonthDeleted]
            ,[RowsDeleted])
        SELECT 'Transactions'    As DataType
           ,'Delete'             As [Description]
            ,GetDate()           AS DateDeleted
            ,@StartingDeleteDate AS MonthDeleted
            ,@NbrOfTransactions  AS RowsDeleted


    SET @StartingDeleteDate = DATEADD(m,1,@StartingDeleteDate)
    SET @NbrOfMonthsToBeDeleted = @NbrOfMonthsToBeDeleted - 1

END;

结果如下:

Delete 15,183,513 transactions between 2019-07-01 AND 2019-07-31

(15183513 rows affected)

(1 row affected)
Delete 14,999,308 transactions between 2019-08-01 AND 2019-08-31

(14999308 rows affected)

(1 row affected)
Delete 14,292,165 transactions between 2019-09-01 AND 2019-09-30

(14292165 rows affected)

(1 row affected)
Delete 15,365,025 transactions between 2019-10-01 AND 2019-10-31

(15365025 rows affected)

(1 row affected)
Delete 14,576,586 transactions between 2019-11-01 AND 2019-11-30

(14576586 rows affected)

(1 row affected)
Delete 15,316,013 transactions between 2019-12-01 AND 2019-12-31

(15316013 rows affected)

(1 row affected)
Delete 15,453,046 transactions between 2020-01-01 AND 2020-01-31

(15453046 rows affected)

(1 row affected)
Delete 14,408,066 transactions between 2020-02-01 AND 2020-02-29

Msg 9002, Level 17, State 4, Line 50
The transaction log for database 'MyDatabase' is full due to 'ACTIVE_TRANSACTION'.

Msg 9002, Level 17, State 4, Line 1
The transaction log for database 'MyDatabase' is full due to 'ACTIVE_TRANSACTION'.

Msg 3314, Level 21, State 3, Line 1

检查一下,

DECLARE @MaxPostDate AS DATE = '2021-01-31'
DECLARE @MinPostDate AS DATE = '2019-07-01'

DECLARE @NbrOfMonthsToMaintain As INT = 13 
begin try

SET NOCount ON
SET XACT_ABORT ON
WHILE @NbrOfMonthsToBeDeleted >= 0
BEGIN 

    --SELECT @NbrOfTransactions = COUNT(*) 
    --FROM [dbo].[Transaction] f
    --WHERE f.[PostDate] BETWEEN @StartingDeleteDate AND EOMONTH(@StartingDeleteDate)

    set @StartingDeleteDate=EOMONTH(@StartingDeleteDate)
   
 
        --BEGIN TRANSACTION

            DELETE f
            FROM [dbo].[Transaction] f
            WHERE (f.[PostDate]>= @StartingDeleteDate AND f.[PostDate]<= @StartingDeleteDate)
            --AND f.[PostDate] <= @DeleteToDate

        --COMMIT TRANSACTION

        @NbrOfTransactions =@@RowCount

         PRINT 'Delete ' + FORMAT(@NbrOfTransactions,'N0') + ' transactions between ' 
                    + CAST(@StartingDeleteDate As VARCHAR(20)) + ' AND ' 
                    + CAST(@StartingDeleteDate AS VARCHAR(20))

        INSERT INTO [app].[DataDeletionHistory](
             [DataType] 
            ,[Description]
            ,[DateDeleted]
            ,[MonthDeleted]
            ,[RowsDeleted])
        SELECT 'Transactions'    As DataType
           ,'Delete'             As [Description]
            ,GetDate()           AS DateDeleted
            ,@StartingDeleteDate AS MonthDeleted
            ,@NbrOfTransactions  AS RowsDeleted


    SET @StartingDeleteDate = DATEADD(m,1,@StartingDeleteDate)
    SET @NbrOfMonthsToBeDeleted = @NbrOfMonthsToBeDeleted - 1

END
end try
begin catch
if(@@ROWCOUNT>0)
Rollback;
Throw;
end catch

您也可以使用 Output Deleted 来了解 count(*)

你也可以玩玩tblTransaction的Primary Key来做bulk delete或batch delete

Link 1 Link 2 Link 3