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」テーブルに挿入された値を取得しています。

ただし、「Update ScriptTable」がある 2 番目の部分は、スクリプト テーブルのすべての行を更新します。カーソルが移動する適切な行の ID を指定する必要があることはわかっています。質問は、どうすればそれを行うことができますか? 適切な行を更新するだけではなく、次の行に移動してからその行を更新します。

Q2: 次の質問は、CATCH ブロックで、ScriptTable のスクリプト列のクエリの 1 つにエラーが発生するとすぐに無限ループを作成していると思います。結果を見ると、そのまま続行されます。そして行きます。ブレイクしたくありません。Err 列にエラーを書き込み、@Script の最後に到達するまで次の行を続行し、停止するための手順。

Scripts テーブルに何も挿入していないため、IDENT_CURRENT、Scope_Identity などは機能しません。

助けてください。

4

3 に答える 3

3

Q1 に関しては、更新にカーソルを使用するには主キーが必要です (回避策はありますが)。
一般に、次のような構文が必要になります。

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

Q2に関しては、それが無限ループであることは理にかなっています. TRYand句を使用して失敗すると、 「領域」CATCHの構文は実行されません。TRYそのため、FETCH NEXTスキップされ、次のループで同じエラーが再び発生します。ループ内に
常に a があることを確認してください。FETCH NEXT

これが少し役立つことを願っています。

于 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 に答える