EXECUTE 后的事务计数指出缺少了 COMMIT 或 ROLLBACK TRANSACTION 语句。原计数 = 0,当前计数 = 1。
2011-08-25 09:59
447 查看
EXECUTE 后的事务计数指出缺少了 COMMIT 或 ROLLBACK TRANSACTION 语句。原计数 = 0,当前计数 = 1。
这是我错误的存储过程,在这个存储过程里,我想做的是开始一个事务,设置这个事务的保存点,更新库存,如果库存更新失败,或者没有符合条件的数据行被更新,就返回出错,否则,添加提货单,如果提货单添加时出错,同样返回到一开始设置的保存点,否则,我就返回成功的信息
create proc a_stationery_useAdd ( @return int out, @rid int, @eid int, @trueName varchar(30), @num int, @useDay smalldatetime, @operatorEid int, @operatorTrueName varchar(30), @uid int, @una varchar(30), @remark varchar(400) ) as
begin transaction trn_useAdd
save transaction stk_useAdd
--update stock
update T_stationery_stock
set stocks = stocks - @num
where rid = @rid and ( stocks > @num or stocks = @num )
if @@error<>0 or @@rowcount = 0
begin
select @return = -2
raiserror('办公用品无效,或者库存量小于领用数量', 16 ,1)
rollback transaction stk_useAdd
return
end
--add bill of lading
insert into T_stationery_billLading
( rid, eid, trueName, num, useDay, operatorEid, operatorTrueName, uid, una, createTime, remark )
values
( @rid, @eid, @trueName, @num, @useDay, @operatorEid, @operatorTrueName, @uid, @una, getdate(), @remark )
if @@error<>0 or @@rowcount = 0
begin
select @return = -3
rollback transaction stk_useAdd
return
end
select @return = 1
commit transaction
分析上面的代码,可以发现两个错误的地方
1、save transaction stk_useAdd设置在事务一开始的时候,这个不是错误,就是这样的设置是重复的,没有用的,因为
BEGIN TRANSACTION 代表一点,由连接引用的数据在该点是逻辑和物理上都一致的。如果遇上错误,在 BEGIN TRANSACTION 之后的所有数据改动都能进行回滚,以将数据返回到已知的一致状态。每个事务继续执行直到它无误地完成并且用 COMMIT TRANSACTION 对数据库作永久的改动,或者遇上错误并且用 ROLLBACK TRANSACTION 语句擦除所有改动。
begin transaction trn_useAdd
save transaction stk_useAdd
这样的连续两个语句,使stk_useAdd和trn_useAdd都是保存在同一个状态下,这两个保存点,是完全一样的,所以没有必要在一开始的时候设置保存点
2、就是sql给出的出错信息“EXECUTE 后的事务计数指出缺少了 COMMIT 或 ROLLBACK TRANSACTION 语句。原计数 = 0,当前计数 = 1。”
这个出错信息是因为我没有很好的理解事务和保存点的关系,保存点是在事务内部的
不带 savepoint_name 和 transaction_name 的 ROLLBACK TRANSACTION 回滚到事务的起点。嵌套事务时,该语句将所有内层事务回滚到最远的 BEGIN TRANSACTION 语句。在这两种情况下,ROLLBACK TRANSACTION 均将 @@TRANCOUNT 系统函数减为 0。ROLLBACK TRANSACTION savepoint_name 不减少 @@TRANCOUNT。
ROLLBACK TRANSACTION 语句若指定 savepoint_name 则不释放任何锁。
在存储过程中,ROLLBACK TRANSACTION 语句不影响调用该过程的批处理中的后续语句;将执行批处理中的后续语句。在触发器中,ROLLBACK TRANSACTION 语句终止含有激发触发器的语句的批处理;不执行批处理中的后续语句。
智() 12:02:49 你对save的点做回滚后提交不会影响整个事务
就是说,我在trn_useAdd事务里,设置了一个保存点stk_useAdd,在执行出错的时候,我把数据rollback到stk_useAdd,就是stk_useAdd是在事务内部的,事务trn_useAdd本身,并没有被提交,也没有被回滚,所以@@TRANCOUNT不会清零,由trn_useAdd造成的锁,也不会被解锁
所以,如果是在事务里rollback到一个保存点,后return,就需要在return前提交或者回滚事务
看下面这一段,我把保存点设置在事务运行的中间,这种形式的保存点,和返回才是正确的
begin transaction trn_example
update tableName set fieldName = @value
save transaction stk_savePoint
update tableName2 set fieldName2 = @value2
if @@error<>0
begin
rollback transaction stk_savePoint
commit transaction
return
end
else
begin
if @@rowcount = 0
rollback transaction
end
commit transaction
如果第二个update出现错误,就返回到第一个update后提交,并且使用return截断后面的语句继续运行
如果第二个update正确执行,就是更新的行数是0,就回滚整个事务,把第一个update执行的结果也取消
这是我错误的存储过程,在这个存储过程里,我想做的是开始一个事务,设置这个事务的保存点,更新库存,如果库存更新失败,或者没有符合条件的数据行被更新,就返回出错,否则,添加提货单,如果提货单添加时出错,同样返回到一开始设置的保存点,否则,我就返回成功的信息
create proc a_stationery_useAdd ( @return int out, @rid int, @eid int, @trueName varchar(30), @num int, @useDay smalldatetime, @operatorEid int, @operatorTrueName varchar(30), @uid int, @una varchar(30), @remark varchar(400) ) as
begin transaction trn_useAdd
save transaction stk_useAdd
--update stock
update T_stationery_stock
set stocks = stocks - @num
where rid = @rid and ( stocks > @num or stocks = @num )
if @@error<>0 or @@rowcount = 0
begin
select @return = -2
raiserror('办公用品无效,或者库存量小于领用数量', 16 ,1)
rollback transaction stk_useAdd
return
end
--add bill of lading
insert into T_stationery_billLading
( rid, eid, trueName, num, useDay, operatorEid, operatorTrueName, uid, una, createTime, remark )
values
( @rid, @eid, @trueName, @num, @useDay, @operatorEid, @operatorTrueName, @uid, @una, getdate(), @remark )
if @@error<>0 or @@rowcount = 0
begin
select @return = -3
rollback transaction stk_useAdd
return
end
select @return = 1
commit transaction
分析上面的代码,可以发现两个错误的地方
1、save transaction stk_useAdd设置在事务一开始的时候,这个不是错误,就是这样的设置是重复的,没有用的,因为
BEGIN TRANSACTION 代表一点,由连接引用的数据在该点是逻辑和物理上都一致的。如果遇上错误,在 BEGIN TRANSACTION 之后的所有数据改动都能进行回滚,以将数据返回到已知的一致状态。每个事务继续执行直到它无误地完成并且用 COMMIT TRANSACTION 对数据库作永久的改动,或者遇上错误并且用 ROLLBACK TRANSACTION 语句擦除所有改动。
begin transaction trn_useAdd
save transaction stk_useAdd
这样的连续两个语句,使stk_useAdd和trn_useAdd都是保存在同一个状态下,这两个保存点,是完全一样的,所以没有必要在一开始的时候设置保存点
2、就是sql给出的出错信息“EXECUTE 后的事务计数指出缺少了 COMMIT 或 ROLLBACK TRANSACTION 语句。原计数 = 0,当前计数 = 1。”
这个出错信息是因为我没有很好的理解事务和保存点的关系,保存点是在事务内部的
不带 savepoint_name 和 transaction_name 的 ROLLBACK TRANSACTION 回滚到事务的起点。嵌套事务时,该语句将所有内层事务回滚到最远的 BEGIN TRANSACTION 语句。在这两种情况下,ROLLBACK TRANSACTION 均将 @@TRANCOUNT 系统函数减为 0。ROLLBACK TRANSACTION savepoint_name 不减少 @@TRANCOUNT。
ROLLBACK TRANSACTION 语句若指定 savepoint_name 则不释放任何锁。
在存储过程中,ROLLBACK TRANSACTION 语句不影响调用该过程的批处理中的后续语句;将执行批处理中的后续语句。在触发器中,ROLLBACK TRANSACTION 语句终止含有激发触发器的语句的批处理;不执行批处理中的后续语句。
智() 12:02:49 你对save的点做回滚后提交不会影响整个事务
就是说,我在trn_useAdd事务里,设置了一个保存点stk_useAdd,在执行出错的时候,我把数据rollback到stk_useAdd,就是stk_useAdd是在事务内部的,事务trn_useAdd本身,并没有被提交,也没有被回滚,所以@@TRANCOUNT不会清零,由trn_useAdd造成的锁,也不会被解锁
所以,如果是在事务里rollback到一个保存点,后return,就需要在return前提交或者回滚事务
看下面这一段,我把保存点设置在事务运行的中间,这种形式的保存点,和返回才是正确的
begin transaction trn_example
update tableName set fieldName = @value
save transaction stk_savePoint
update tableName2 set fieldName2 = @value2
if @@error<>0
begin
rollback transaction stk_savePoint
commit transaction
return
end
else
begin
if @@rowcount = 0
rollback transaction
end
commit transaction
如果第二个update出现错误,就返回到第一个update后提交,并且使用return截断后面的语句继续运行
如果第二个update正确执行,就是更新的行数是0,就回滚整个事务,把第一个update执行的结果也取消
相关文章推荐
- EXECUTE后的事务计数指出缺少了COMMIT或ROLLBACK TRANSACTION语句。原计数=0,当前计数=1。
- EXECUTE 后的事务计数指示缺少了 COMMIT 或 ROLLBACK TRANSACTION 语句。上一计数 = 1,当前计数 = 2
- 关于EXECUTE 后的事务计数指示缺少了 COMMIT 或 ROLLBACK TRANSACTION 语句。上一计数
- EXECUTE 后的事务计数指示缺少了 COMMIT 或 ROLLBACK TRANSACTION 语句
- EXECUTE 后的事务计数指示缺少了 COMMIT 或 ROLLBACK TRANSACTION 语句
- System.Data.SqlClient.SqlException (0x80131904): EXECUTE 后的事务计数指示 BEGIN 和 COMMIT 语句的数目不匹配。上一计数 = 1,当前计数 = 0。 EXECUTE 后的事务计数指示 BEGIN 和 COMMIT 语句的数目不匹配。上一计数 = 1,当前计数 = 0。
- EXECUTE 后的事务计数指示 BEGIN 和 COMMIT 语句的数目不匹配。上一计数 = 0,当前计数 = 1。
- EXECUTE 后的事务计数指示 BEGIN 和 COMMIT 语句的数目不匹配。上一计数 = 0,当前计数 = 1。
- 消息 266,级别 16,状态 2,过程 UserExchange,第 0 行 EXECUTE 后的事务计数指示 BEGIN 和 COMMIT 语句的数目不匹配。上一计数 = 0,当前计数 = 1。
- EXECUTE 后的事务计数指示 BEGIN 和 COMMIT 语句的数目不匹配
- SqlServer中嵌套事务使用--事务计数指示 BEGIN 和 COMMIT 语句的数目不匹配 --根本问题
- SqlServer中嵌套事务使用--事务计数指示 BEGIN 和 COMMIT 语句的数目不匹配 --根本问题
- 处理DB2 数据COMMIT和ROLLBACK语句和事务边界
- SqlServer中嵌套事务使用--事务计数指示 BEGIN 和 COMMIT 语句的数目不匹配 --根本问题
- mysql事务,START TRANSACTION, COMMIT和ROLLBACK,SET AUTOCOMMIT语法
- 处理 DB2 数据 COMMIT 和 ROLLBACK 语句和事务边界
- Oracle:数据操作语句 (DML-insert into,update,delete) 部分、事务控制 (TCL-commit,rollback)
- spring事务(Transaction )报 marked as rollback-only异常的原因及解决方法
- [mysql]beginTransaction/rollback/commit
- oracle 中--怎么查看当前表空间在作什么操作?--查锁,死锁,当前执行时间长的Sql语句,没提交的事务,对象为哪些进程所用