前回の続き
前回から、トランザクションの実装をしてますが、今回はエラーを検知してロールバックしてみたいと思います。
エラー検知
エラー検知はこのような構文です。
BEGIN TRY -- ############################### -- ここでエラーが発生したらCATCHに飛ばす -- ############################### END TRY BEGIN CATCH -- ############################### -- エラーがあったらここの内容を処理する -- ############################### END CATCH
こんな感じです。
前回の内容に組み込んでみる。
では、早速やってみましょう。
IF OBJECT_ID(N'tempdb..#TEMP', N'U') IS NOT NULL DROP TABLE #TEMP CREATE TABLE #TEMP ( NUM BIGINT, TXT NVARCHAR(10) ) BEGIN TRY BEGIN TRANSACTION DECLARE @CNT INT SET @CNT = 0 WHILE @CNT <= 30 BEGIN INSERT INTO #TEMP VALUES( POWER(2, @CNT), '2^' + CONVERT(VARCHAR, @CNT) ) IF @CNT = 20 SET @CNT = @CNT / 0 SET @CNT += 1 END COMMIT TRANSACTION END TRY BEGIN CATCH ROLLBACK TRANSACTION END CATCH SELECT * FROM #TEMP
上記の内容は、WHILEのループ内で@CNTが20の時に、わざとエラーを発生させています。
エラーをキャッチしてロールバックしているので、#TEMPはからになって、最後に出力されます。
こんな感じです。
ロールバックしないで、エラーが出るまで処理をする
通常、エラーがでたら処理がとまってしまうのですが、TRY~CATCHはうまくエラーをハンドリングすることができます。
では、エラーがでるまで処理するというよみましょう。
IF OBJECT_ID(N'tempdb..#TEMP', N'U') IS NOT NULL DROP TABLE #TEMP CREATE TABLE #TEMP ( NUM BIGINT, TXT NVARCHAR(10) ) BEGIN TRY BEGIN TRANSACTION DECLARE @CNT INT SET @CNT = 0 WHILE @CNT <= 30 BEGIN INSERT INTO #TEMP VALUES( POWER(2, @CNT), '2^' + CONVERT(VARCHAR, @CNT) ) IF @CNT = 20 SET @CNT = @CNT / 0 SET @CNT += 1 END COMMIT TRANSACTION END TRY BEGIN CATCH PRINT('##### ERROR #####') PRINT('@CNT -> ' + CONVERT(VARCHAR, @CNT)) PRINT('##### ERROR #####') RETURN END CATCH SELECT * FROM #TEMP
上記の内容は、WHILEのループ内で@CNTが20の時に、わざとエラーを発生させています。
@CNTを0で割ろうとしていますが、分母が0になる数は存在しないので、エラーになります。
こんなかんじの出力です。
@CNTが20でおわっているのが確認できますね。
BEGIN CATCH以下の内容を確認しておこう。
BEGIN CATCH PRINT('##### ERROR #####') PRINT('@CNT -> ' + CONVERT(VARCHAR, @CNT)) PRINT('##### ERROR #####') RETURN END CATCH SELECT * FROM #TEMP
こんなかんじですが、RETURNで処理を終了しています。
つまり、それ以下のSELECT * FROM #TEMPは処理されないということになります。
SELECT * FROM #TEMPは、もしエラーが発生されなかったら処理されるといことになります。
こんなかんじで、エラーがあったときにそこで終わるのかどうかということも明示しておく必要があります。
以上、今回はここまで。S