1

我在 SQL 中有以下游标:

DECLARE @Script varchar(max)

DECLARE @getScript CURSOR

SET @getScript = CURSOR FOR

SELECT [Script]
FROM ScriptTable

OPEN @getScript
FETCH NEXT
FROM @getScript INTO @Script

WHILE @@FETCH_STATUS = 0
BEGIN
    BEGIN TRY
        EXEC(@Script) --Working part.  This executes the query stored in the Script column.
                      --For example INSERT INTO zTest VALUES(VAL1, VAL2, etc etc..)

        UPDATE ScriptTable
        SET DateDone = GETDATE(), IsDone = 1, Err = NULL
        FETCH NEXT
        FROM @getScript INTO @Script 
    END TRY
    BEGIN CATCH
        DECLARE @Err varchar(max)
        SET @Err = ERROR_MESSAGE()

        UPDATE ScriptTable
        SET DateDone = GETDATE(), Err = @Err

    END CATCH
END

CLOSE @getScript
DEALLOCATE @getScript

Q1: 目前,当我执行 EXEC(@Script) 时,我正在将值插入到我的注释中指定的“zTest”表中。

但是,“更新脚本表”所在的第二部分会更新我的脚本表中的所有行。我知道我需要为光标正在移动的相应行指定 ID。问题是,我该怎么做?我不想只更新适当的行,移动到下一个然后更新那个。

Q2: 我的下一个问题是,在 CATCH 块中,我认为只要 ScriptTable 的 Script 列中的一个查询出现错误,我就会创建一个无限循环,因为当我查看结果时,它只会继续和去。我不想打破;该过程因为我想将错误写入 Err 列并继续下一行,直到它到达@Script 的末尾,然后停止。

IDENT_CURRENT、Scope_Identity 等不起作用,因为我没有在脚本表中插入任何内容。

请帮忙。

4

3 回答 3

3

关于 Q1,您必须有一个主键才能使用游标进行更新(尽管有解决方法)。
一般来说,你会想要这样的语法:

update ScriptTable
 SET DateDone = GETDATE(), IsDone = 1, Err = NULL
where ID of @getScript

关于第二季度,它是一个无限循环是有道理的。当您使用TRYandCATCH子句并且它失败时,它不会执行TRY“区域”中的任何语法。因此FETCH NEXT被跳过,并且在下一个循环中再次发生相同的错误。
尝试确保FETCH NEXT循环中始终存在 a。

希望这对您有所帮助。

于 2013-09-02T15:55:29.777 回答
2

如果有人感兴趣,这是我的最终代码:

DECLARE @Script varchar(max)

        DECLARE @getScript CURSOR

        SET @getScript = CURSOR FOR

        SELECT [Script]
        FROM ScriptControl

        OPEN @getScript
        FETCH NEXT
        FROM @getScript INTO @Script

        DECLARE @Counter int = 1
        WHILE @@FETCH_STATUS = 0
        BEGIN
            BEGIN TRY
                EXEC(@Script)

                    UPDATE ScriptControl 
                    SET DateDone = GETDATE(), IsDone = 1, Error = NULL WHERE ID = @Counter

                FETCH NEXT
                FROM @getScript INTO @Script 

                SET @Counter = (@Counter + 1)
            END TRY
            BEGIN CATCH
                DECLARE @Err varchar(max)
                SET @Err = ERROR_MESSAGE()

                UPDATE ScriptControl 
                SET CSC_EOD_DateDone = NULL, CSC_EOD_Err = @Err, CSC_EOD_IsDone = 0 WHERE CURRENT OF @getScript

                FETCH NEXT
                FROM @getScript INTO @Script

                SET @Counter = (@Counter + 1)
            END CATCH
        END

        CLOSE @getScript
        DEALLOCATE @getScript
于 2013-09-03T07:40:58.813 回答
1

这个:

DECLARE @ScriptControlId INT, @Script VARCHAR(MAX)

DECLARE @getScript CURSOR
SET @getScript = CURSOR FOR
SELECT [ID], [Script]
FROM ScriptControl

OPEN @getScript
FETCH NEXT
FROM @getScript INTO @ScriptControlId, @Script

WHILE @@FETCH_STATUS = 0
BEGIN
    BEGIN TRY
        EXEC(@Script)

        UPDATE ScriptControl 
        SET DateDone = GETDATE(), IsDone = 1, Error = NULL
        WHERE ID = @ScriptControlId

        FETCH NEXT FROM @getScript INTO @ScriptControlId, @Script
    END TRY
    BEGIN CATCH
        DECLARE @Err VARCHAR(MAX) = ERROR_MESSAGE()

        UPDATE ScriptControl 
        SET DateDone = NULL, Error = @Err, IsDone = 0
        WHERE CURRENT OF @getScript

        FETCH NEXT FROM @getScript INTO @ScriptControlId, @Script
    END CATCH
END

CLOSE @getScript
DEALLOCATE @getScript

或这个:

DECLARE @Script VARCHAR(MAX)

DECLARE @getScript CURSOR
SET @getScript = CURSOR FOR
SELECT [Script]
FROM ScriptControl

OPEN @getScript
FETCH NEXT
FROM @getScript INTO @Script

WHILE @@FETCH_STATUS = 0
BEGIN
    BEGIN TRY
        EXEC(@Script)

        UPDATE ScriptControl 
        SET DateDone = GETDATE(), IsDone = 1, Error = NULL
        WHERE CURRENT OF @getScript

        FETCH NEXT FROM @getScript INTO @Script
    END TRY
    BEGIN CATCH
        DECLARE @Err VARCHAR(MAX) = ERROR_MESSAGE()

        UPDATE ScriptControl 
        SET DateDone = NULL, Error = @Err, IsDone = 0
        WHERE CURRENT OF @getScript

        FETCH NEXT FROM @getScript INTO @Script
    END CATCH
END

CLOSE @getScript
DEALLOCATE @getScript
于 2014-07-03T15:10:53.610 回答