SQL-执行后的事务计数表示不匹配
我正在MS SQL Server Management Studio 2012中开发一个存储过程 我正在重用其他过程中的一些代码,这包括使用SQL-执行后的事务计数表示不匹配,sql,sql-server,stored-procedures,Sql,Sql Server,Stored Procedures,我正在MS SQL Server Management Studio 2012中开发一个存储过程 我正在重用其他过程中的一些代码,这包括使用EXEC命令调用另一个存储过程 此过程将对象的信息作为参数,重置该对象的状态,然后查找相关(下游)对象并重置其状态 代码正在工作,但需要进行小的更改以重置和相关对象的状态,即使它未处于错误状态。为了解决这个问题,我在迭代相关对象的主循环之前创建了一个变量,然后当遇到第一个具有错误状态的对象时,它设置变量的值。变量本身是一个位 程序如下: USE [DB_TE
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
变量
我确实看到过一些文章提到这个问题可能是在这个调用的存储过程中,但我有点犹豫,因为存储过程是有效的,这些错误只在尝试设置变量值时出现。只是一个猜测。。但我认为会发生以下情况:
希望有帮助。我终于找到了一种使存储过程工作的方法 我所做的是从设置变量值的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