17

SQL Server (2008r2) プロシージャをコーディングしていて、それをトランザクションでラップする場合、それを明示的に try..catch ブロックで囲み、明示的に catch ブロックでロールバックを呼び出す必要がありますか? それとも終了して終了しますか?単独で同じものをロールバックしますか?

すなわち:

これはどのようにしますか:

    begin transaction

    begin try
    delete from....

    insert into...
    end try
    begin catch
    rollback transaction
    return
    end catch

    commit transaction

と比べて:

    begin transaction
    delete from....

    insert into...
    commit transaction

助けてくれてありがとう。

4

3 に答える 3

19

あなたの質問への答えはSET XACT_ABORT設定によって異なります:

Transact-SQLステートメントで実行時エラーが発生したときにSQLServerが現在のトランザクションを自動的にロールバックするかどうかを指定します。

SET XACT_ABORTがONのときに、Transact-SQLステートメントで実行時エラーが発生すると、トランザクション全体が終了してロールバックされます。

SET XACT_ABORTがOFFの場合、エラーを発生させたTransact-SQLステートメントのみがロールバックされ、トランザクションは処理を続行する場合があります。エラーの重大度によっては、SETXACT_ABORTがOFFの場合でもトランザクション全体がロールバックされる場合があります。 デフォルト設定はOFFです。

構文エラーなどのコンパイルエラーは、SETXACT_ABORTの影響を受けません。

たとえば、次のコードを試してください。最初の0による除算はエラーを発生させますが、実行を継続します。2番目のゼロ除算はエラーを発生させ、実行を停止します。

begin transaction

set xact_abort off
    
select 1 / 0 -- causes divide by zero error, but continues
select @@trancount -- returns 1

set xact_abort on

select 1 / 0 -- causes divide by zero error and terminates execution
select @@trancount -- we never get here

rollback

XACT_ABORTがONの場合、エラーによってトランザクションが中止されるため、TRY/CATCHは必要ありません。

XACT_ABORTがOFFの場合、各ステートメントのステータスをチェックして、エラーが発生したかどうかを確認する必要があります。

begin transaction

delete from...
if @@error <> 0
begin
    if @@trancount > 0
        rollback
    return
end

insert into...
if @@error <> 0
begin
    if @@trancount > 0
        rollback
    return
end

commit

ただし、TRY / CATCHが必要な場合は、エラーが発生したときに何か特別なことをする必要があるかもしれません。その場合は、例外処理を試行/キャッチすることを忘れないでください。

begin transaction

set xact_abort on

begin try
    select 1 / 0 -- causes divide by zero error and terminates execution
    select @@trancount -- we never get here
    commit
end try
begin catch
    select xact_state() -- this will be -1 indicating you MUST rollback before doing any other operations
    select @@trancount -- this will probably be one, because we haven't ended the transaction yet
    if xact_state() <> 0
    begin try
        select 'rollback'
        rollback
        
        -- do something to handle or record the error before leaving the current scope
        select 'exception processing here'
        --insert into...
    end try
    begin catch
        -- ignore rollback errors
    end catch
    
end catch
于 2012-06-08T14:04:01.693 に答える
4

ほとんどのケースでエラーが発生した場合、ロールバックが自動的に発生しますが、すべてではありません。

すべてのエラーのロールバックを保証したい場合は、SET XACT_ABORT ON でトランザクションを開始する前に

ベスト プラクティスは、try-catch ブロックで明示的にエラーをキャッチし、ロールバックやエラーの報告/ログ記録などのアクションを実行することです。

于 2012-06-08T13:59:11.883 に答える
0

エラーの重大度レベルによって異なります。十分に高い -- おそらく 16? -- 失敗した行でプロセスが停止し、トランザクションが開かれたままロックされたままになる可能性があります。トランザクション内でエラーが発生する可能性がある場合は、最初の例で行ったように、間違いなく try-catch ブロックでラップする必要があります。

于 2012-06-08T14:00:13.507 に答える