EXECUTE 后的事务计数指示缺少了 COMMIT 或 ROLLBACK TRANSACTION 语句。上一计数 = 0,当前计数 = 1。分析

ALTER PROCEDURE [dbo].[cor_InsertServerConfig]
 (
 @ServerName varchar(20),
 @ServerIP varchar(20),
 @ServerCategory varchar(25),
 @ServerState  char(1),
 @ServerAbility int
 --@ID  int output
  
 )

AS
 DECLARE @ID INT

BEGIN transaction

 
 
 SET NOCOUNT ON;

    IF EXISTS  (  SELECT 1 FROM [ServerConfig] WHERE ServerName =  @ServerName)
    BEGIN
     --return 0
 --SELECT @ID = 0
  SET @ID = 0
    RETURN @ID
 END
   
 ELSE
 BEGIN

 INSERT INTO [ServerConfig](ServerName,ServerIP,ServerCategory,ServerState,ServerAbility)
 VALUES (@ServerName,@ServerIP,@ServerCategory,@ServerState,@ServerAbility)
 


 --SELECT ID FROM INSERTED  --C#里'INSERTED'对象名无效
  --SELECT SCOPE_IDENTITY()
 
  set @ID = @@identity

  commit transaction

  ---select @ID 非Output,而是return,用select 即使成功插入返回的也为0 


  return @ID 
 
END

当SELECT 1 FROM [ServerConfig] WHERE ServerName =  @ServerName时出现上面的错误。

Begin Tran

....

Commit Tran

中间不能出现 return,因为BEGIN TRANSACTION 语句将 @@TranCount加 1。ROLLBACK TRANSACTION 将 @@TranCount递减到 0,  return 使执行进程返回,但并没有使事务计数器减一,所以出现了语句执行后事务计数器出现不一致的情况....

ALTER PROCEDURE [dbo].[cor_InsertServerConfig]
 (
 @ServerName varchar(20),
 @ServerIP varchar(20),
 @ServerCategory varchar(25),
 @ServerState  char(1),
 @ServerAbility int
 --@ID  int output
  
 )

AS
 DECLARE @ID INT

BEGIN transaction

 
 
 SET NOCOUNT ON;

    IF EXISTS  (  SELECT 1 FROM [ServerConfig] WHERE ServerName =  @ServerName)
    BEGIN
     --return 0
 --SELECT @ID = 0
  SET @ID = 0
     ROLLBACK TRANSACTION
  RETURN @ID
 END
   
 ELSE
 BEGIN

 INSERT INTO [ServerConfig](ServerName,ServerIP,ServerCategory,ServerState,ServerAbility)
 VALUES (@ServerName,@ServerIP,@ServerCategory,@ServerState,@ServerAbility)
 


 --SELECT ID FROM INSERTED  --C#里'INSERTED'对象名无效
  --SELECT SCOPE_IDENTITY()
 
  set @ID = @@identity

  commit transaction

  ---select @ID 非Output,而是return,用select 即使成功插入返回的也为0 


  return @ID 
 
   
 
END

这样就正确了。

另外这种情况

ALTER PROCEDURE [dbo].[sp_test]

AS

BEGIN

    SET NOCOUNT ON;

    set   xact_abort   on

--开始显式声明事务

    begin   tran

    INSERT INTO [testDB].[dbo].[test]

           ([name])

     VALUES

           (CAST(getdate() AS nvarchar(20)))

    return @@rowcount

    commit   tran


END

执行时出现了“ EXECUTE 后的事务计数指示缺少了 COMMIT 或 ROLLBACK TRANSACTION 语句

到Google上查找原因,发现是
“如果某存储过程退出时其   @@TRANCOUNT   值与进入该存储过程时不同,则 SQL Server 返回错误   266。 ”

再到MSDN上找原因,发现这么一条备注
BEGIN TRANSACTION 语句将 @@TRANCOUNT 加 1。ROLLBACK TRANSACTION 将 @@TRANCOUNT 递减到 0,但 ROLLBACK TRANSACTION savepoint_name 除外,它不影响 @@TRANCOUNT。COMMIT TRANSACTION 或 COMMIT WORK 将 @@TRANCOUNT 递减 1。

此时,原因已经明了了,出在这句话上:

    return @@rowcount

    commit   tran

return 使执行进程返回,但并没有使事务计数器减一,所以出现了语句执行后事务计数器出现不一致的情况,报告“消息 266,级别 16,状态 2,过程 sp_test,第 0 行”错误。


猜你喜欢

转载自corrinejtt.iteye.com/blog/1330483