从停止SQL的位置恢复WHILE循环

时间:2017-03-19 20:34:32

标签: sql-server tsql while-loop

我有一个while循环查询,我只想运行到每天晚上11点 - 我知道这可以通过WAITFOR语句来实现,然后只是结束查询。

然而,在第二天,一旦我重新运行我的查询,我希望它从最后一次运行停止的地方继续。所以我正在考虑创建一个包含最后处理过的ID的日志表。

我怎样才能做到这一点?

DECLARE @MAX_Value BIGINT  = ( SELECT MAX(ID) FROM dbo.TableA )

DECLARE @MIN_Value BIGINT = ( SELECT MIN(ID) FROM dbo.TableA )

            WHILE (@MIN_Value < @MAX_Value )
            BEGIN

                INSERT INTO dbo.MyResults
                /* Do some processing*/
                ….
                ….
                ….

                SET @MIN_Value = MIN_Value + 1

            /*I only want the above processing to run until 11PM*/

            /* Once it’s 11PM, I want to save the last used @MIN_Value 
            into my LoggingTable (dbo.Logging) and kill the above processing.*/

        /* Once I re-run the query I want my processing to restart from the
 above @MIN_Value which is recorded in dbo.Logging */

            END

1 个答案:

答案 0 :(得分:1)

免责声明:我不建议在SQL Server中使用WHILE循环,但考虑到您希望在SQL中使用解决方案的注释,请转到:

-- First of all, I strongly recommend using a different way of assigning variable values to avoid scenarios with the variable being NULL when the table is empty, also you can do it in a single select.

-- Also, if something started running at 10:59:59 it will let the processing for the value finish and will not simply rollback at 11.

CREATE TABLE dbo.ProcessingValueLog (
    LogEntryId BIGINT IDENTITY(1,1) NOT NULL,
    LastUsedValue BIGINT NOT NULL,
    LastUsedDateTime DATETIME NOT NULL DEFAULT(GETDATE()),
    CompletedProcessing BIT NOT NULL DEFAULT(0)
)

DECLARE @MAX_Value BIGINT = 0;
DECLARE @MIN_Value BIGINT = 0;

SELECT
    @MIN_Value = MIN(ID),
    @MAX_Value = MAX(ID)
FROM
    dbo.TableA

SELECT TOP 1
    @MIN_Value = LastUsedValue
FROM
    dbo.ProcessingValueLog
WHERE
    CompletedProcessing = 1
ORDER BY
    LastUsedDateTime DESC

DECLARE @CurrentHour TINYINT = HOUR(GETDATE());
DECLARE @LogEntryID BIGINT;

WHILE (@MIN_Value < @MAX_Value AND @CurrentHour < 23)
BEGIN

    INSERT INTO dbo.ProcessingValueLog (LastUsedValue)
    VALUE(@MIN_Value)

    SELECT @LogEntryID = SCOPE_IDENTITY()

    // Do some processing...

    SET @MIN_Value = @MIN_Value + 1;

    UPDATE dbo.ProcessingValueLog
    SET CompletedProcessing = 1
    WHERE LogEntryId = @LogEntryID

    SET @CurrentHour = HOUR(GETDATE())
END