0

少し複雑な質問があります。パラメータを取らないストアド プロシージャがあります。現在、実行すると、エラーメッセージが表示されます

after EXECUTE は、BEGIN ステートメントと COMMIT ステートメントの数が一致していないことを示します。前のカウント = 0、現在のカウント = 1。

本質的に、ストアド プロシージャは次のようになります。

    USE FirstDatabase
    GO

    SET ANSI_NULLS ON
    GO

    SET QUOTED_IDENTIFIER ON
    GO

    CREATE PROCEDURE [schema].[Procedure]
    AS

    SET NOCOUNT ON
    SET XACT_ABORT ON

    BEGIN TRY

DECLARE @WholeBunchOfVariables varchar(max); --All these are ofcourse separated and different data types

IF(SELECT OBJECT_ID('tempdb..#tempTable')) IS NOT NULL
BEGIN
    DROP TABLE #tempTable
END

CREATE TABLE #tempTable (
    ...,  --bunch of fields to be populated
    IsProcessed bit) -- this field is used later to run through a temp table variable one record at a time, once done, this is set to 1

DECLARE @tempTableVar TABLE (
    ...)

    --Insert data from the accounts table(s) into the temp table.  Only process data
    --that has been modified in the past day.

    INSERT INTO #tempTable
    SELECT DISTINCT
        ... -- bunch of fields from different tables
    FROM
        SomeTables

    --Loop through the data in the temp table, one record at a time.  Process it and 
    --once done, set the IsProcessed field in the temp table to 1 so that it can pick 
    --up the next record to process.

    WHILE (1=1)
    BEGIN

    INSERT INTO @tempTableVar
SELECT TOP 1
    ... --bunch of fields from temp table
FROM
    #tempTable
WHERE
    IsProcessed = 0  -- check for first unprocessed record

    --The following variables need to be initiated so that it can be used for executing 
    --The main stored procedure that popuplates the marketing tables.

    SELECT
        ... --bunch of variables initiated from the temp table variable
    FROM
        @tempTableVar

    BEGIN TRY

    BEGIN TRANSACTION

    IF (SELECT COUNT(*) FROM @tempTableVar) = 0
    BEGIN
            BREAK;
        ROLLBACK TRANSACTION;
    END

    --Another stored procedure is called here to be executed with the variables that 
    --were initiated a bit further up, as input parameters.


    EXEC [SomeDatabase].[Schema].[SomeOtherStoredProcedure]
        ... --bunch of input parameters / variables

COMMIT TRANSACTION

    END TRY

    BEGIN CATCH

IF (XACT_STATE() <> 0)
ROLLBACK TRAN;

SELECT 
        @ErrorNumber = ERROR_NUMBER(),
    @ErrorSeverity = ERROR_SEVERITY(),
    @ErrorState = ERROR_STATE(),
    @ErrorLine = ERROR_LINE(),
    @ErrorProcedure = ISNULL(ERROR_PROCEDURE(), '-');

SELECT @ErrorMessage = ERROR_MESSAGE() +  '(Error %d, Level %d, State %d, Procedure %s, Line %d).'

    --Errors on this level, essentially raised by the secondary stored procedure, are
    --stored in an error logging table for later reference

    INSERT INTO [schema].[ImportErrors] (
        ErrorType,
        ErrorMessaae) VALUES (
        'Some Type',
        @ErrorMessage);

UPDATE
    #tempTable
SET
    IsProcessed = 1
WHERE
    someField = @someVariable ...

DELETE
FROM
    @tempTableVar

    END CATCH

    --Update the temp table's IsProcessed field to 1 for the affected record, if there 
    --are no errors.

    UPDATE #tempTable
    SET
        IsProcessed = 1
    WHERE
        someField = @someVariable ...

    --Delete the entry from the temp table variable so that it can be used for the next
    --record.

    DELETE
    FROM
        @tempTableVar

    END

    IF(SELECT OBJECT_ID('tempdb..#tempTable')) IS NOT NULL
    BEGIN
        DROP TABLE #tempTable
    END

    SET NOCOUNT OFF
    SET XACT_ABORT OFF

    END TRY

    BEGIN CATCH

        IF (XACT_STATE() <> 0)
            ROLLBACK TRAN;

        -- Do the error handling.
        -- Assign variables to error-handling functions that 
        -- capture information for RAISERROR.
        SELECT 
            @ErrorNumber = ERROR_NUMBER(),
            @ErrorSeverity = ERROR_SEVERITY(),
            @ErrorState = ERROR_STATE(),
            @ErrorLine = ERROR_LINE(),
            @ErrorProcedure = ISNULL(ERROR_PROCEDURE(), '-');

        -- Building the message string that will contain original
        -- error information.
        SELECT @ErrorMessage =
    'Message: '+ ERROR_MESSAGE() + N' (Error %d, Level %d, State %d, Procedure %s, Line %d).';

--SELECT @ErrorMessage = @ErrorMessage + @CustomerCategoryID + ' ' + @CustomerID + ' ' + @EmailAddress

-- Raise an error: msg_str parameter of RAISERROR will contain
-- the original error information.
RAISERROR (
    @ErrorMessage, 
    @ErrorSeverity, 
    1,
    @ErrorNumber,    -- parameter: original error number.
    @ErrorSeverity,  -- parameter: original error severity.
    @ErrorState,     -- parameter: original error state.
    @ErrorProcedure, -- parameter: original error procedure name.
    @ErrorLine);       -- parameter: original error line number.

    END CATCH

誰かが私が間違っていることを教えてもらえますか?

4

1 に答える 1

0

これは解析するコードがたくさんあります。コードには多くのトランザクションの開始/終了があり、ロールバック/コミットする前に、トランザクションがまだ開いているかどうかを確認する前にチェックしていません。

理想的には、挿入の論理セットごとに 1 つのトランザクション コミット/ロールバック ステートメントが必要です。

于 2012-08-15T12:49:37.730 に答える