SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

EnterpriseZine(エンタープライズジン)編集部では、情報システム担当、セキュリティ担当の方々向けに、EnterpriseZine Day、Security Online Day、DataTechという、3つのイベントを開催しております。それぞれ編集部独自の切り口で、業界トレンドや最新事例を網羅。最新の動向を知ることができる場として、好評を得ています。

直近開催のイベントはこちら!

EnterpriseZine編集部ではイベントを随時開催しております

EnterpriseZine(エンタープライズジン)編集部では、情報システム担当、セキュリティ担当の方々向けの講座「EnterpriseZine Academy」や、すべてのITパーソンに向けた「新エバンジェリスト養成講座」などの講座を企画しています。EnterpriseZine編集部ならではの切り口・企画・講師セレクトで、明日を担うIT人材の育成をミッションに展開しております。

お申し込み受付中!

あたらしいSQL Server/Denaliの世界

New T-SQL in Denali (前編)

#009


エラーハンドリング

 Denaliでは、新しくTHROWステートメントが追加されます。THROWステートメントを使用すると、ユーザーは任意のタイミングでエラーを発生させることができます。

 これまでにSQL Serverを使用されたことのある方はお気づきかもしれませんが、T-SQLには、ユーザーが任意のタイミングでエラーを発生させるためのRAISERRORステートメントが既にあります。エラーを発生させるという意味において、THROWステートメントと、RAISERRORステートメントは同じです。

 では、何が大きく異なるのかというと、THROWステートメントは、TRY…CATCH構造でキャッチしたエラーを、そのまま上位へスローすることができるようになるのです。RAISERRORステートメントでは、TRY…CATCH構造でキャッチしたエラーを、そのまま上位へスローという機能を備えていませんでした。

 例えば、キャッチしたエラーを、上位へスローしようとして以下のように実装しても実際にはうまく機能しません。

…
END TRY
BEGIN CATCH
    DECLARE @ErrorMessage NVARCHAR(4000);
    DECLARE @ErrorSeverity INT;
    DECLARE @ErrorState INT;
    DECLARE @Err INT;

    SELECT 
	@ErrorMessage = ERROR_MESSAGE(),
        @ErrorSeverity = ERROR_SEVERITY(),
        @ErrorState = ERROR_STATE(),
        @Err =  ERROR_NUMBER()
        
    RAISERROR (@Err,
                @ErrorMessage,
                @ErrorSeverity,
                @ErrorState);
END CATCH

 第一に、RAISERRORの第一引数に指定できるエラー番号は、50000以上の値でないといけないため、50000以下のシステムエラーの場合にRAISERRORステートメントがエラーとなります。第二に、エラー番号が50000以上のエラーであっても、TRYブロック内のRAISERRORステートメントでエラーを発生させたときに指定したパラメータ(エラーメッセージの置換文字列)を受け取るすべがないので、まったく同じようにRAISERRORでエラーを発生させることができません。キャッチブロック内のRAISERRORステートメントの第一引数を、エラー番号の代わりにERROR_MESSAGE関数で取得したエラーメッセージにすることも考えられますが、そうすると今度はエラー番号がデフォルトの50000となってしまいます。

 これまでは、このような制限があったため、RAISERRORとTRY…CATCH構造を使用する場合のエラーハンドリングについてはあらかじめ考慮しておかなければならない点も多く、多少煩わしい部分もあったかと思います。しかし、上記のような例で困っていた方は、DenaliでTHROWステートメントが実装されることで随分と楽になるはずです。

 では、簡単ではありますがTHROWステートメントを使用して、エラーを上位へスローする例を以下に紹介します。

…
END TRY
BEGIN CATCH
    INSERT SAMPLE_THROW VALUES (@@ERROR);
    THROW;
END CATCH

 この例では、エラーをキャッチした後、SAMPLE_THROWテーブルにINSERTして、キャッチした上位へエラーをスローしています。キャッチしたエラーをそのまま上位へスローする場合は、THROWステートメントのパラメータに何も指定しません。お気づきの方もいらっしゃるとは思いますが、一番のポイントはTHROWステートメントで上位へスローされるエラーは、あくまでキャッチしたエラーであり、INSERT文が実行された直後のエラーではないことです。なお、この動作を保障する為には、THROWステートメント直前のステートメントがすべてセミコロン(;)で終わってなければならないので注意が必要です。

 THROWステートメントは、RAISERRORステートメントとよく似ていますが、他にも異なる点がいくつかあります。例えば、THROWステートメントはパラメータに重大度を指定できなくなっており、固定で16が設定されます。これも重要な点です。

  RAISERRORステートメントは、重大度を指定できるがゆえに、エラーハンドリングを複雑化させていた部分があります。RAISERRORステートメントに指定する重大度によっては、バッチがアボートしたり、接続がアボートするなど、エラー時のアクションが異なることがあるからです。(必ずしも”重大度 = エラー時のアクション”ではないので注意)

 THROWステートメントの詳細については、こちらを参照ください。RAISERRORステートメントと異なる点についても表でわかりやすくまとめられています。

 * * *

 いかがだったでしょうか?今回紹介した機能は、実際に私がお客様から「こういう機能があるといいな」というお声をいただいたことのある機能です。そのため、「待っていました!」と思われた方も結構いらっしゃるかもしれません。

 Denaliでは、まだまだ他にもT-SQLの新機能が実装されていますので、次回も引き続きT-SQLの新機能紹介を行っていきます。おたのしみに!

この記事は参考になりましたか?

  • Facebook
  • Twitter
  • Pocket
  • note
あたらしいSQL Server/Denaliの世界連載記事一覧

もっと読む

この記事の著者

古賀 啓一郎(コガ ケイイチロウ)

日本マイクロソフト株式会社勤務。きままなエンジニア。
謎があると解決せずにはいられない性格。
週末は家事に従事。 

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

EnterpriseZine(エンタープライズジン)
https://enterprisezine.jp/article/detail/3555 2012/02/10 18:11

Job Board

AD

おすすめ

アクセスランキング

アクセスランキング

イベント

EnterpriseZine(エンタープライズジン)編集部では、情報システム担当、セキュリティ担当の方々向けに、EnterpriseZine Day、Security Online Day、DataTechという、3つのイベントを開催しております。それぞれ編集部独自の切り口で、業界トレンドや最新事例を網羅。最新の動向を知ることができる場として、好評を得ています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング