SQL-执行后的事务计数表示不匹配

SQL-执行后的事务计数表示不匹配,sql,sql-server,stored-procedures,Sql,Sql Server,Stored Procedures,我正在MS SQL Server Management Studio 2012中开发一个存储过程 我正在重用其他过程中的一些代码,这包括使用EXEC命令调用另一个存储过程 此过程将对象的信息作为参数,重置该对象的状态,然后查找相关(下游)对象并重置其状态 代码正在工作,但需要进行小的更改以重置和相关对象的状态,即使它未处于错误状态。为了解决这个问题,我在迭代相关对象的主循环之前创建了一个变量,然后当遇到第一个具有错误状态的对象时,它设置变量的值。变量本身是一个位 程序如下: USE [DB_TE

我正在MS SQL Server Management Studio 2012中开发一个存储过程

我正在重用其他过程中的一些代码,这包括使用
EXEC
命令调用另一个存储过程

此过程将对象的信息作为参数,重置该对象的状态,然后查找相关(下游)对象并重置其状态

代码正在工作,但需要进行小的更改以重置和相关对象的状态,即使它未处于错误状态。为了解决这个问题,我在迭代相关对象的主循环之前创建了一个变量,然后当遇到第一个具有错误状态的对象时,它设置变量的值。变量本身是一个

程序如下:

USE [DB_TEST]
GO

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

ALTER          PROC [dbo].[resetTasksInErrorStatus]
    @TaskId                         INT,
    @SubjectId                      INT,
    @ProjectProtocolId              INT,
    @TimePointId                    INT,
    @WorkbookId                     INT,
    @LogCreatorUserId               INT,
    @LogReasonTypeId                INT,
    @LogOtherReason                 VARCHAR(256),
    @SignatureCaptured              BIT,
    @ManualChangeTaskStatus         BIT,
    @ErrorIfModifiedAfter           DATETIME,       
    @NewTaskStatusID                INT,            
    @ProcessorUserId                INT

AS
BEGIN
    SET NOCOUNT ON;

    BEGIN TRANSACTION ResetTasksInError

    -- Make sure the task has not been modified since the reset was requested
    IF(EXISTS(
        SELECT ti.* FROM TaskInstance as ti
        WHERE ti.ModifyDate > @ErrorIfModifiedAfter
            AND ti.TaskId = @TaskId
            AND ti.SubjectId = @SubjectId
            AND ti.ProjectProtocolId = @ProjectProtocolId
            AND ti.TimePointId = @TimePointId
            AND ti.WorkbookId = @WorkbookId))
    BEGIN
        RAISERROR('The task to be reset was modified before the reset could complete', 16, 1);
        GOTO error
    END

    -- Get all downstream task instances
    SELECT *
    INTO #downstreamTaskInstances
    from dbo.fnGetTaskInstancesDownstream
    (
        @TaskId,
        @SubjectId,
        @TimePointId
    )

    -- Get the previous task status
    DECLARE @OldTaskStatus INT;
    SELECT TOP 1 @OldTaskStatus = ti.TaskStatusTypeId FROM TaskInstance as ti
    WHERE ti.TaskId = @TaskId
        AND ti.SubjectId = @SubjectId
        AND ti.TimePointId = @TimePointId

    -- Reset the task
    EXEC setTaskStatus
        @TaskID,
        @SubjectId,
        @ProjectProtocolId,
        @TimePointId,
        @WorkBookId,
        @OldTaskStatus,
        @NewTaskStatusID,
        @ProcessorUserId,
        @LogCreatorUserId,
        @LogReasonTypeId,
        @LogOtherReason,
        @SignatureCaptured,
        @ManualChangeTaskStatus,
        NULL,
        NULL,
        NULL,
        1

    -- Check if setTaskStatus rolled back our transaction
    IF(@@TRANCOUNT = 0)
    BEGIN
        RAISERROR('Error in sub procedure. Changes rolled back.', 16, 1);
        RETURN
    END

    -- Set a boolean variable to determine whether downstream tasks should be reset
    DECLARE @ResetDownstreamTasks BIT = 0;
    --Set @ResetDownstreamTasks = 0;

    -- Create a cursor of the downstream tasks
    DECLARE downstreamCursor CURSOR FOR
        SELECT TaskId, TimePointId, ProcessorUserId, TaskStatus, WorkBookId, ProjectProtocolId, IsManual, TaskStatus
        FROM #downstreamTaskInstances
    OPEN downstreamCursor

    -- Reset each downstream task to unprocessed
    DECLARE @CursorTaskID INT;
    DECLARE @CursorTimePointID INT;
    DECLARE @CursorProcessorUserId INT;
    DECLARE @CursorTaskStatusID INT;
    DECLARE @CursorWorkBookId INT;
    DECLARE @CursorProjectProtocolId INT;
    DECLARE @CursorIsManual BIT;
    Declare @CursorTaskStatus INT;
    FETCH NEXT FROM downstreamCursor INTO @CursorTaskID, @CursorTimePointId, @CursorProcessorUserId, @CursorTaskStatusID, @CursorWorkBookId, @CursorProjectProtocolId, @CursorIsManual, @CursorTaskStatus
    WHILE @@FETCH_STATUS = 0 AND @@ERROR = 0 AND @@TRANCOUNT = 1
    BEGIN
        -- Check if the task is in error status, and then make sure it is not an manual task.
        -- Manual tasks should never be in error status, so there is no need to reset them.
        if @CursorTaskStatus = 10 and @CursorIsManual <> 1
        begin
                SET @ResetDownstreamTasks = 1;

                EXEC setTaskStatus
                    @CursorTaskID,
                    @SubjectId,
                    @CursorProjectProtocolId,
                    @CursorTimePointId,
                    @CursorWorkBookId,
                    @CursorTaskStatusID,
                    1, -- Unprocessed
                    @CursorProcessorUserId,
                    @LogCreatorUserId,
                    @LogReasonTypeId,
                    @LogOtherReason,
                    @SignatureCaptured,
                    @ManualChangeTaskStatus,
                    NULL,
                    NULL,
                    NULL,
                    0
        end;


        if @ResetDownstreamTasks = 1
        begin
            EXEC setTaskStatus
                @CursorTaskID,
                @SubjectId,
                @CursorProjectProtocolId,
                @CursorTimePointId,
                @CursorWorkBookId,
                @CursorTaskStatusID,
                6, -- Inspected
                @CursorProcessorUserId,
                @LogCreatorUserId,
                @LogReasonTypeId,
                @LogOtherReason,
                @SignatureCaptured,
                @ManualChangeTaskStatus,
                NULL,
                NULL,
                NULL,
                0
        end

      FETCH NEXT FROM downstreamCursor INTO @CursorTaskID, @CursorTimePointId, @CursorProcessorUserId, @CursorTaskStatusID, @CursorWorkBookId, @CursorProjectProtocolId, @CursorIsManual, @CursorTaskStatus
    END

    DROP TABLE #downstreamTaskInstances
    CLOSE downstreamCursor
    DEALLOCATE downstreamCursor

    -- Check if setTaskStatus rolled back our transaction
    IF(@@TRANCOUNT = 0)
    BEGIN
        RAISERROR('Error in sub procedure. Changes rolled back.', 16, 1);
        RETURN
    END

    IF(@@ERROR <> 0)
    BEGIN
        GOTO ERROR
    END

    COMMIT TRANSACTION  ResetTasksInError
    RETURN

    ERROR:
        RAISERROR('Error encountered. Changes rolled back.', 16,1);
        ROLLBACK TRANSACTION ResetTasksInError
        RETURN
END
如果我注释掉
SET…
语句,则过程将运行并工作(不符合要求)

我四处寻找类似的问题,但没有一个能解决我的问题

关于SET语句,我缺少什么吗

它是否以某种方式影响了
@@TRANCOUNT
变量


我确实看到过一些文章提到这个问题可能是在这个调用的存储过程中,但我有点犹豫,因为存储过程是有效的,这些错误只在尝试设置变量值时出现。

只是一个猜测。。但我认为会发生以下情况:

  • 您可以在事务内创建临时表
  • 启动一个游标并在其中迭代,直到其中一个内部SP出现错误
  • 事务被回滚,因此临时表将与事务一起使用
  • 光标给出了架构更改错误
  • 丢包错误
  • 因此,您应该检查其中一个内部SP中的错误


    希望有帮助。

    我终于找到了一种使存储过程工作的方法

    我所做的是从设置变量值的if语句中删除存储过程
    EXEC
    语句

    循环中的代码如下所示:

    WHILE @@FETCH_STATUS = 0 AND @@ERROR = 0 AND @@TRANCOUNT = 1
        BEGIN
            -- Check if the task is in error status, and then make sure it is not an manual task.
            -- Manual tasks should never be in error status, so there is no need to reset them.
            if @CursorTaskStatus = 10 and @CursorIsManual <> 1
            begin
                    SET @ResetDownstreamTasks = 1;
            end;
    
    
            if @ResetDownstreamTasks = 1
            begin
                EXEC setTaskStatus
                    @CursorTaskID,
                    @SubjectId,
                    @CursorProjectProtocolId,
                    @CursorTimePointId,
                    @CursorWorkBookId,
                    @CursorTaskStatusID,
                    6, -- Inspected
                    @CursorProcessorUserId,
                    @LogCreatorUserId,
                    @LogReasonTypeId,
                    @LogOtherReason,
                    @SignatureCaptured,
                    @ManualChangeTaskStatus,
                    NULL,
                    NULL,
                    NULL,
                    0
            end
    
          FETCH NEXT FROM downstreamCursor INTO @CursorTaskID, @CursorTimePointId, @CursorProcessorUserId, @CursorTaskStatusID, @CursorWorkBookId, @CursorProjectProtocolId, @CursorIsManual, @CursorTaskStatus
        END
    
    WHILE@@FETCH\u STATUS=0和@ERROR=0和@tracount=1
    开始
    --检查任务是否处于错误状态,然后确保它不是手动任务。
    --手动任务不应处于错误状态,因此无需重置它们。
    如果@CursorTaskStatus=10且@CursorsManual 1
    开始
    设置@ResetDownstreamTasks=1;
    结束;
    如果@ResetDownstreamTasks=1
    开始
    执行setTaskStatus
    @卡索尔塔斯基德,
    @主观性,
    @CursorProjectProtocolId,
    @CursorTimePointId,
    @CursorWorkBookId,
    @CursorTaskStatusID,
    6,--检查
    @CursorProcessorUserId,
    @LogCreatorUserId,
    @LogReasonTypeId,
    @LogOtherReason,
    @签名许可,
    @手动更改任务状态,
    无效的
    无效的
    无效的
    0
    结束
    从下游Ursor获取下一个到@CursorTaskID、@CursorTimePointId、@CursorProcessorUserId、@CursorTaskStatusID、@CursorWorkBookId、@CursorProjectProtocolId、@cursorsmanual、@CursorTaskStatus
    结束
    
    关于此过程的操作,您肯定是正确的。我已经开始研究内部存储过程以发现任何问题。谢谢
    WHILE @@FETCH_STATUS = 0 AND @@ERROR = 0 AND @@TRANCOUNT = 1
        BEGIN
            -- Check if the task is in error status, and then make sure it is not an manual task.
            -- Manual tasks should never be in error status, so there is no need to reset them.
            if @CursorTaskStatus = 10 and @CursorIsManual <> 1
            begin
                    SET @ResetDownstreamTasks = 1;
            end;
    
    
            if @ResetDownstreamTasks = 1
            begin
                EXEC setTaskStatus
                    @CursorTaskID,
                    @SubjectId,
                    @CursorProjectProtocolId,
                    @CursorTimePointId,
                    @CursorWorkBookId,
                    @CursorTaskStatusID,
                    6, -- Inspected
                    @CursorProcessorUserId,
                    @LogCreatorUserId,
                    @LogReasonTypeId,
                    @LogOtherReason,
                    @SignatureCaptured,
                    @ManualChangeTaskStatus,
                    NULL,
                    NULL,
                    NULL,
                    0
            end
    
          FETCH NEXT FROM downstreamCursor INTO @CursorTaskID, @CursorTimePointId, @CursorProcessorUserId, @CursorTaskStatusID, @CursorWorkBookId, @CursorProjectProtocolId, @CursorIsManual, @CursorTaskStatus
        END