1

失敗した場合に一部のデータをクリーンアップする必要があるストアド プロシージャを作成していinsertます。クリーンアップを実行したいのですが、この挿入が失敗した場合は元のエラーを返します (insert失敗した理由を正確に確認したいので、主にログ記録用)。基本的には in のようthrow;ですC#。これを行う簡単な方法はありますか?

BEGIN TRY
    Insert into table (col1) values ('1")
END TRY
BEGIN CATCH
    --do clean up here
    --then throw original error
END TRY

これは実行可能/良い習慣ですか? proc を呼び出すアプリケーション コードでは、アプリケーションの観点からエラーを処理していますが、クリーンアップ ステートメントは proc 内により適しているようです。

4

3 に答える 3

0

私は通常、次のようなことをします:

IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = object_id(N'[dbo].[procedure_name]') AND ObjectProperty(id, N'IsProcedure') = 1)
    DROP PROCEDURE [dbo].[procedure_name]
GO

CREATE PROCEDURE [dbo].[procedure_name]
(
    @param1 VARCHAR(100)
   ,@param2 INT
)

AS

/*
*******************************************************************************
<Name>
[procedure_name]
</Name>

<Purpose>
[Purpose]
</Purpose>

<Notes>
</Notes>

<OutsideRef>
Called From: [Called From]
</OutsideRef>

<ChangeLog>
Change No:   Date:          Author:       Description:                          
_________    ___________    __________    _____________________________________
   001       [DATE]         [YOU]         Created.                           
</ChangeLog>
*******************************************************************************
*/
BEGIN
    SET NOCOUNT ON
    SET XACT_ABORT OFF -- Allow procedure to continue after error

    -- *****************************************
    -- Parameter string. Used for error handling
    -- *****************************************
    DECLARE  @ErrorNumber       INT 
            ,@ErrorMessage      VARCHAR(400)
            ,@ErrorSeverity     INT
            ,@ErrorState        INT
            ,@ErrorLine         INT
            ,@ErrorProcedure    VARCHAR(128)
            ,@ErrorMsg          VARCHAR(2000)
            ,@NestedProc        BIT = 1
            ,@Params            VARCHAR(255);    -- String representing parameters, make it an appropriate size given your parameters.

    --Be Careful of the CONVERT here, GUIDs (if you use them) need 36 characters, ints need 10, etc.        
    SET @Params = ''
                + CHAR(13) + '@param1 = ' + COALESCE(CONVERT(VARCHAR(100), @param1), 'NULL') 
                + CHAR(13) + '@param2 = ' + COALESCE(CONVERT(VARCHAR(10), @param2), 'NULL')

    BEGIN TRY
        --If you're using transactions, and want an 'all or nothing' approach, use this so that
        --you only start a single transaction in the outermost calling procedure (or handle 
        --that through your application layer)
        IF @@TRANCOUNT = 0
        BEGIN
            SET @NestedProc = 0
            BEGIN TRANSACTION
        END

        INSERT INTO [TABLE]
            (
             COL1
            ,COL2
            )
        VALUES
            (
             @param1
            ,@param2
            );

        --Commit the transaction if this is the outtermost procedure and if there is a transaction to rollback.
        IF @@TRANCOUNT > 0 AND @NestedProc = 0
        BEGIN
            COMMIT TRANSACTION
        END
    END TRY

    BEGIN CATCH
        --Roll back the transaction if this is the outtermost procedure and if there is a transaction to rollback.
        IF @@TRANCOUNT > 0 AND @NestedProc = 0
        BEGIN
            ROLLBACK TRANSACTION
        END

        -- Execute the error retrieval routine.
        SELECT 
            @ErrorNumber = ERROR_NUMBER(),
            @ErrorSeverity = ERROR_SEVERITY(),
            @ErrorProcedure = ERROR_PROCEDURE(),
            @ErrorState = ERROR_STATE(),
            @ErrorLine = ERROR_LINE(),
            @ErrorMessage = ERROR_MESSAGE();

        SET @ErrorMsg = 'Error Number   : ' + CAST(@ErrorNumber AS VARCHAR(5)) + CHAR(13)
                      + 'Procedure Name : ' + @ErrorProcedure + CHAR(13)
                      + 'Procedure Line : ' + CAST(@ErrorLine AS VARCHAR(5)) + CHAR(13)
                      + 'Error Message  : ' + @ErrorMessage + CHAR(13)
                      + 'Parameters     : ' + CHAR(13) + @Params + CHAR(13);

        --Raise the exception.
        RAISERROR (@ErrorMsg, @ErrorSeverity, @ErrorState);
    END CATCH
END
GO

このタイプのプロシージャを使用すると、トランザクションでネストされたプロシージャを使用できます (エラーがどこかでスローされた場合に、最終的に外側のプロシージャにスローバックしてからロールバックすることが望ましい効果である限り)。このテンプレートが処理するとは思わない非常に重要なシナリオは、プロシージャを完全に強制終了するほど重大なエラーが発生した場合です。おそらく、他の誰かがその面でチャイムを鳴らすことができます.

于 2013-05-10T20:10:56.750 に答える
-1

次のスニペットを試してください。

DECLARE @errNum int
DECLARE @rowCount int

BEGIN TRY
    INSERT INTO [TABLE] (COL1) VALUES ('1")
END TRY
BEGIN CATCH
    SET @errNum = @@ERROR
    SET @rowCount = @@ROWCOUNT
    RAISEERROR(@errNum)
END CATCH
于 2013-01-07T20:16:26.187 に答える