存储过程中的事务:为什么一个事务中的某个INSERT语句失败了,数据不全部回滚,竟然删掉了???

booksfount 2003-09-08 05:05:51
存储过程内容如下:

CREATE PROCEDURE [op_carry_data]
@rtn int output
AS
declare @ErrorSave int

begin tran --开始事务了

insert into menuwater_c --执行成功了
select *
from menuwater where m_account=1

set @ErrorSave= @ErrorSave+@@error

insert into fmenuwater_c --执行成功了
select *
from fmenuwater where f_mcode in (select m_mcode from menuwater where m_account=1)

set @ErrorSave= @ErrorSave+@@error

delete from fmenuwater where f_mcode in (select m_mcode from menuwater where m_account=1)--执行成功了

set @ErrorSave= @ErrorSave+@@error

delete from menuwater where m_account=1--执行成功了

set @ErrorSave= @ErrorSave+@@error

if @ErrorSave<>0
begin

rollback tran
SELECT @rtn= - 10
print @rtn
return
end


--下面的INSERT出错了
insert into fgoodinout_c
select *
from fgoodinout

set @ErrorSave=@ErrorSave+@@error

insert into goodinout_c --这个INSERT也出错了

select *
from goodinout

set @ErrorSave=@ErrorSave+@@error

delete from goodinout --这个也删掉了
set @ErrorSave=@ErrorSave+@@error

delete from fgoodinout--这个也删掉了

set @ErrorSave=@ErrorSave+@@error

if @ErrorSave<>0
begin
rollback tran --可是这里已经ROLLBACK了?????
select @rtn= - 20
print @rtn
return
end
--结转完毕

--
UPDATE jstock
SET s_oldnum = isnull(s_currentnum,0) +isnull(s_oldnum,0 )

set @ErrorSave=@ErrorSave+@@error

if @ErrorSave<>0
begin
rollback tran
select @rtn= - 60
print @rtn
return
end
--结转完毕

--结账供应上的本期挂账

UPDATE victualer SET v_oldmoney=isnull( v_oldmoney,0) + isnull(v_money,0)

set @ErrorSave=@ErrorSave+@@error

if @ErrorSave<>0
begin
rollback tran
select @rtn= - 80
print @rtn
return
end
else
begin

SELECT @rtn=100
commit tran
end

return
GO


在执行到insert into fgoodinout_c时开始出错了,因为我没有每条语句都判断,所以连后面的DELETE也执行了。但是我已经set @ErrorSave=@ErrorSave+@@error,也判断了if @ErrorSave<>0 就ROLLBACK,可是为什么就是不ROLLBACK 呢???,包括上面所有执行成功的都应该一起ROLLBACK呀,为什么也没有?????


谢谢大家帮帮忙!到底问题出在那里了??????????
...全文
220 点赞 收藏 9
写回复
9 条回复
切换为时间正序
当前发帖距今超过3年,不再开放新的回复
发表回复
booksfount 2003-09-08
我明白了,是不是如前面 yujohny(踏网无痕) 说的,仅用一个rollback tran ,我的rollback tran用得多了,是错的,造成了事务不能够回滚,所以用goto
回复
booksfount 2003-09-08
TO :pengdali(大力 V3.0) :今天,我搜了很多贴子查,大都发现用了
GOTO LB_ERROR
但我想不明白,他们的效果为什么是不一样的????

LB_ERROR:
rollback tran
print @rtn
return
也是执行这三句话,我如果不用GOTO也是执行这几句然后RETRUN了,表面上看,好像一样的???
区别是什么呢???可否再详细些?谢谢啦!

回复
booksfount 2003-09-08
谢谢大家的帮助!

TO CrazyFor(蚂蚁) :如果我使用了SET XACT_ABORT ON ,是不是所有的ROLLBACK TRAN全部可以省略了,并且也不用判断@ERROR了???

TO:yujohny(踏网无痕) :我对事物确实是稀里糊涂的
------
你存储过程就用一个begin tran和一个rollback tran
-------
我这样写是不是问题多多,可否详细指教一下



TO: liuyun2003(流云(疯狂想去南宁中))
我的语句部分INSERT成功,部分因为故意制造了一些错误,所以INSERT不成功了!
回复
yujohny 2003-09-08
CREATE PROCEDURE [op_carry_data]
@rtn int output
AS

DECLARE @ErrorSave INT

begin tran --开始事务了

insert into menuwater_c --执行成功了
select *
from menuwater where m_account=1

IF @@error <> 0
BEGIN
SET @rtn = -10
GOTO LB_ERROR
END

insert into fmenuwater_c --执行成功了
select *
from fmenuwater where f_mcode in (select m_mcode from menuwater where m_account=1)

IF @@error <> 0
BEGIN
SET @rtn = -10
GOTO LB_ERROR
END

delete from fmenuwater where f_mcode in (select m_mcode from menuwater where m_account=1)--执行成功了

IF @@error <> 0
BEGIN
SET @rtn = -10
GOTO LB_ERROR
END

delete from menuwater where m_account=1--执行成功了

IF @@error <> 0
BEGIN
SET @rtn = -10
GOTO LB_ERROR
END


--下面的INSERT出错了
insert into fgoodinout_c
select *
from fgoodinout

IF @@error <> 0
BEGIN
SET @rtn = -20
GOTO LB_ERROR
END

insert into goodinout_c --这个INSERT也出错了

select *
from goodinout

IF @@error <> 0
BEGIN
SET @rtn = -20
GOTO LB_ERROR
END

delete from goodinout --这个也删掉了
IF @@error <> 0
BEGIN
SET @rtn = -20
GOTO LB_ERROR
END

delete from fgoodinout--这个也删掉了

IF @@error <> 0
BEGIN
SET @rtn = -20
GOTO LB_ERROR
END

--结转完毕

--
UPDATE jstock
SET s_oldnum = isnull(s_currentnum,0) +isnull(s_oldnum,0 )

IF @@error <> 0
BEGIN
SET @rtn = -60
GOTO LB_ERROR
END

--结转完毕

--结账供应上的本期挂账

UPDATE victualer SET v_oldmoney=isnull( v_oldmoney,0) + isnull(v_money,0)

IF @@error <> 0
BEGIN
SET @rtn = -80
GOTO LB_ERROR
END

SELECT @rtn=100
commit tran
return

LB_ERROR:
rollback tran
print @rtn
return

GO
回复
pengdali 2003-09-08
CREATE PROCEDURE [op_carry_data]
@rtn int output
AS
declare @ErrorSave int

begin tran --开始事务了

insert menuwater_c select * from menuwater where m_account=1

if @@error<>0 goto error1

insert fmenuwater_c --执行成功了
select *
from fmenuwater where f_mcode in (select m_mcode from menuwater where m_account=1)

if @@error<>0 goto error1

delete fmenuwater where f_mcode in (select m_mcode from menuwater where m_account=1)--执行成功了

if @@error<>0 goto error1

delete from menuwater where m_account=1--执行成功了

if @@error<>0 goto error1



--下面的INSERT出错了
insert into fgoodinout_c
select *
from fgoodinout

if @@error<>0 goto error2

insert into goodinout_c --这个INSERT也出错了

select *
from goodinout

if @@error<>0 goto error2

delete from goodinout --这个也删掉了
if @@error<>0 goto error2

delete from fgoodinout--这个也删掉了

if @@error<>0 goto error2


--结转完毕

--
UPDATE jstock
SET s_oldnum = isnull(s_currentnum,0) +isnull(s_oldnum,0 )

if @@error<>0 goto error3

--结转完毕

--结账供应上的本期挂账

UPDATE victualer SET v_oldmoney=isnull( v_oldmoney,0) + isnull(v_money,0)

if @@error<>0 goto error4


SELECT @rtn=100
commit tran

return

error1:
rollback tran
SELECT @rtn= - 10
print @rtn
return

error2:
rollback tran
select @rtn= - 20
print @rtn
return

error3:
rollback tran
select @rtn= - 60
print @rtn
return

error4:
rollback tran
select @rtn= - 80
print @rtn
return
GO
回复
liuyun2003 2003-09-08
你的添加语句是都错了,还是有几条语句添加进去了?如果有语句添加进去了,那么没有错误码的。
回复
liuyun2003 2003-09-08
你的添加语句是都错了,还是有几条语句添加进去了?如果有语句添加进去了,那么没有错误码的。
回复
yujohny 2003-09-08
你存储过程就用一个begin tran和一个rollback tran

回复
CrazyFor 2003-09-08

Transact-SQL 参考


SET XACT_ABORT
指定当 Transact-SQL 语句产生运行时错误时,Microsoft® SQL Server™ 是否自动回滚当前事务。

语法
SET XACT_ABORT { ON | OFF }

注释
当 SET XACT_ABORT 为 ON 时,如果 Transact-SQL 语句产生运行时错误,整个事务将终止并回滚。为 OFF 时,只回滚产生错误的 Transact-SQL 语句,而事务将继续进行处理。编译错误(如语法错误)不受 SET XACT_ABORT 的影响。

对于大多数 OLE DB 提供程序(包括 SQL Server),隐性或显式事务中的数据修改语句必须将 XACT_ABORT 设置为 ON。唯一不需要该选项的情况是提供程序支持嵌套事务时。有关更多信息,请参见分布式查询和分布式事务。

SET XACT_ABORT 的设置是在执行或运行时设置,而不是在分析时设置。

示例
下例导致在含有其它 Transact-SQL 语句的事务中发生违反外键错误。在第一个语句集中产生错误,但其它语句均成功执行且事务成功提交。在第二个语句集中,SET XACT_ABORT 设置为 ON。这导致语句错误使批处理终止,并使事务回滚。

CREATE TABLE t1 (a int PRIMARY KEY)
CREATE TABLE t2 (a int REFERENCES t1(a))
GO
INSERT INTO t1 VALUES (1)
INSERT INTO t1 VALUES (3)
INSERT INTO t1 VALUES (4)
INSERT INTO t1 VALUES (6)
GO
SET XACT_ABORT OFF
GO
BEGIN TRAN
INSERT INTO t2 VALUES (1)
INSERT INTO t2 VALUES (2) /* Foreign key error */
INSERT INTO t2 VALUES (3)
COMMIT TRAN
GO

SET XACT_ABORT ON
GO

BEGIN TRAN
INSERT INTO t2 VALUES (4)
INSERT INTO t2 VALUES (5) /* Foreign key error */
INSERT INTO t2 VALUES (6)
COMMIT TRAN
GO

/* Select shows only keys 1 and 3 added.
Key 2 insert failed and was rolled back, but
XACT_ABORT was OFF and rest of transaction
succeeded.
Key 5 insert error with XACT_ABORT ON caused
all of the second transaction to roll back. */

SELECT *
FROM t2
GO

DROP TABLE t2
DROP TABLE t1
GO


请参见

BEGIN TRANSACTION

COMMIT TRANSACTION

ROLLBACK TRANSACTION

SET

@@TRANCOUNT

©1988-2000 Microsoft Corporation。保留所有权利。
回复
发帖
疑难问题
创建于2007-09-28

2.1w+

社区成员

MS-SQL Server 疑难问题
申请成为版主
帖子事件
创建了帖子
2003-09-08 05:05
社区公告
暂无公告