2009-04-07 16 views
27

私たちは、主にSQL Server 7.0で書かれた大規模なアプリケーションを持っています。ここでは、すべてのデータベース呼び出しがストアドプロシージャです。 T-SQLの機能が多く提供されているSQL Server 2005が実行されています。SQL ServerのT-SQLエラー処理のベストプラクティスは何ですか?

ほとんどすべてのSELECT、INSERT、UPDATE、およびDELETEの後、@@ ROWCOUNTと@@ ERRORはローカル変数に取り込まれ、問題を評価されます。問題がある場合は、次の行われます。

  • エラーメッセージ出力パラメータが設定されている
  • ロールバック(必要な場合)
  • 情報を行われているがとテーブル
  • リターンをログに記録する(INSERT)に書かれています

これらはすべて行をチェックしません(既知の場合のみ)。多少のログ/デバッグ情報ではいくつかの違いがあります。また、行ロジックはエラーロジックから時々分割されます(WHERE句で並行性フィールドがチェックされる更新ではrows = 0は他の誰かがデータを更新したことを意味します)。しかし、ここにはかなり一般的な例があります:

SELECT, INSERT, UPDATE, or DELETE 

SELECT @[email protected]@ERROR, @[email protected]@ROWCOUNT 
IF @Rows!=1 OR @Error!=0 
BEGIN 
    SET @ErrorMsg='ERROR 20, ' + ISNULL(OBJECT_NAME(@@PROCID), 'unknown') 
           + ' - unable to ???????? the ????.' 
    IF @@TRANCOUNT >0 
    BEGIN 
     ROLLBACK 
    END 

    SET @LogInfo=ISNULL(@LogInfo,'')+'; '+ISNULL(@ErrorMsg,'')+ 
     + ' @YYYYY='  +dbo.FormatString(@YYYYY) 
     +', @XXXXX='  +dbo.FormatString(@XXXXX) 
     +', Error='   +dbo.FormatString(@Error) 
     +', Rows='   +dbo.FormatString(@Rows) 

    INSERT INTO MyLogTable (...,Message) VALUES (....,@LogInfo) 

    RETURN 20 

END 

私はこれをTRY-CATCH T-SQLで置き換える方法を検討しています。私はTRY...CATCH (Transact-SQL)の構文について読んだので、その概要を掲載しないでください。私は良いアイデアを探していますどのように最高私たちのエラー処理方法を行うか、改善する。 Try-Catchでなくても、T-SQLエラー処理の優れたやり方だけを使用することができます。

答えて

29

あなたはこれを読む必要があります。

http://www.sommarskog.se/error-handling-I.html

私は非常に十分にそのリンクをお勧めすることはできません。ちょっと長いですが、良い方法です。

本来、SQL Server 2000用に書かれた免責事項がありますが、SQL Server 2005以降の新しいtry/catchエラー処理機能についても説明しています。

+0

私はそれがSQL Server 2005のものをスキップすると感じますが、とにかく優れています。そして彼のサイトの残りの部分も。 – gbn

+0

SQL Server 2005以降については、http://www.sommarskog.se/error_handling/Part1.html –

3

これは既に非常に優れた処理をしているようです。私はあなたがSQLプログラマーの95%以上をやっていると思う。

あなたがここにいくつかの興味深い情報を見つける必要があります。

ワン[関連性のない]提案: '!='の代わりに '<'を使用して開始してください。

[* SQL Junkiesがなくなったため、2番目の記事は利用できません。 ]

+0

ここでは、 '!='の代わりに '<>'を使用する理由は何ですか? –

+1

ANSI仕様で<>が指定されています。多くのdbも!=をサポートしていますが、標準ではありません。 –

+0

http://www.contrib.andrew.cmu.edu/~shadow/sql/sql1992.txt 5.2を参照してください。 –

6

エラー処理のためのベストプラクティスのセットはありません。あなたのニーズが満たされ、一貫しています。

次は、電話番号を格納するテーブルとストアドプロシージャのサンプルです。

SET ANSI_NULLS ON 
    GO 
    SET QUOTED_IDENTIFIER ON 
    GO 
    SET ANSI_PADDING ON 
    GO 
    CREATE TABLE [dbo].[Phone](
     [ID] [int] IDENTITY(1,1) NOT NULL, 
     [Phone_Type_ID] [int] NOT NULL, 
     [Area_Code] [char](3) NOT NULL, 
     [Exchange] [char](3) NOT NULL, 
     [Number] [char](4) NOT NULL, 
     [Extension] [varchar](6) NULL, 
    CONSTRAINT [PK_Phone] PRIMARY KEY CLUSTERED 
    (
     [ID] ASC 
    )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 
    ) ON [PRIMARY] 

    GO 
    SET ANSI_PADDING OFF 
    GO 
    /**/ 

    CREATE PROCEDURE [dbo].[usp_Phone_INS] 
     @Customer_ID INT 
     ,@Phone_Type_ID INT 
     ,@Area_Code CHAR(3) 
     ,@Exchange CHAR(3) 
     ,@Number CHAR(4) 
     ,@Extension VARCHAR(6) 
    AS 
    BEGIN 
     SET NOCOUNT ON; 

     DECLARE @Err INT, @Phone_ID INT 

     BEGIN TRY 
      INSERT INTO Phone 
       (Phone_Type_ID, Area_Code, Exchange, Number, Extension) 
      VALUES 
       (@Phone_Type_ID, @Area_Code, @Exchange, @Number, @Extension) 
      SET @Err = @@ERROR 
      SET @Phone_ID = SCOPE_IDENTITY() 
      /* 
       Custom error handling expected by the application. 
       If Err = 0 then its good or no error, if its -1 or something else then something bad happened. 
      */ 
      SELECT ISNULL(@Err,-1) AS Err, @Phone_ID 
     END TRY 
     BEGIN CATCH 
      IF (XACT_STATE() <> 0) 
       BEGIN 
        ROLLBACK TRANSACTION 
       END 

      /* 
       Add your own custom error handling here to return the passed in paramters. 
       I have removed my custom error halding code that deals with returning the passed in parameter values. 
      */ 

      SELECT ERROR_NUMBER() AS Err, ISNULL(@Phone_ID,-1) AS ID 
     END CATCH 
    END 
17

我々は現在、(あなたがたとえば、DDL文でそれを必要としない場合は、トランザクションのものを残すことができる)、我々は実行任意のクエリのために、このテンプレートを使用します。もちろん

BEGIN TRANSACTION 
BEGIN TRY 
    // do your SQL statements here 

    COMMIT TRANSACTION 
END TRY 
BEGIN CATCH 
    SELECT 
     ERROR_NUMBER() AS ErrorNumber, 
     ERROR_SEVERITY() AS ErrorSeverity, 
     ERROR_STATE() AS ErrorState, 
     ERROR_PROCEDURE() AS ErrorProcedure, 
     ERROR_LINE() AS ErrorLine, 
     ERROR_MESSAGE() AS ErrorMessage 

    ROLLBACK TRANSACTION 
END CATCH 

をキャッチされた例外をエラーログテーブルに簡単に挿入できます。

これは本当にうまく動作します。コード生成(CodeSmithなど)やカスタムC#コードを使用して、古い格納されたprocsから新しいフォーマットへの変換を自動化することさえ可能です。

+10

TRYブロックの外でトランザクションを開始する理由はありますか? MSDNのすべての例では、TRY http://technet.microsoft.com/en-us/library/ms179296%28v=sql.105%29.aspx – Davos

+2

XACT_STATE内の最初のステートメントとしてBEGIN TRANが表示されますトランザクション:https://msdn.microsoft.com/en-us/library/ms189797.aspx –

関連する問題