存储过程.事务问题.

igelf 2009-07-10 09:26:52
下面这段是第二条语句出错.是能全部回滚的.
SET XACT_ABORT ON 或者OFF 都一样.能全部回滚.
网上找了下.说什么严重错误的话.OFF也一样能回滚.迷茫.

SET XACT_ABORT ON
BEGIN TRAN
insert into testtb(id) values(1);
insert into testtb(id)values('d');
COMMIT TRAN


下面的只能回滚一条.

SET XACT_ABORT ON
BEGIN TRAN
insert into testtb(id) values(1);
exec('insert into testtb(id)values(''d'')');
COMMIT TRAN


没办法上面不能全部回滚.
只好写下面这个

SET XACT_ABORT ON
BEGIN TRAN
insert into testtb(id) values(1);
if @@error<>0
rollback tran
exec('insert into testtb(id)values(''d'')');
if @@error<>0
rollback tran
COMMIT TRAN

这样的话.执行时会出现COMMIT TRANSACTION 请求没有对应的 BEGIN TRANSACTION.

SET XACT_ABORT ON
BEGIN TRAN
insert into testtb(id) values(1);
if @@error<>0
rollback tran
exec('insert into testtb(id)values(''d'')');
if @@error<>0
rollback tran
COMMIT TRAN

最后改了下.
把if @@error<>0
rollback tran
换成下面就好了.
if @@error<>0
begin
rollback tran
return
end

每次操作都要写上这么5段.感觉语句太多了.有没有简洁点的.

...全文
22 21 打赏 收藏 举报
写回复
21 条回复
切换为时间正序
当前发帖距今超过3年,不再开放新的回复
发表回复
igelf 2009-07-10
谢谢.现在清楚了.
sql2000麻烦.
不管中间是否有动态语句.
只要动态语句不出现语法错误.下面这样写都能全部回滚.

SET XACT_ABORT ON
BEGIN TRAN
...
COMMIT TRAN

太粗心了.在测试的时候.动态语句随便打.语法错误,导致不能全部回滚.
  • 打赏
  • 举报
回复
youzhj 2009-07-10
来学习学习,顶了
  • 打赏
  • 举报
回复
csdyyr 2009-07-10
--联机帮助
当 SET XACT_ABORT 为 ON 时,如果执行 Transact-SQL 语句产生运行时错误,则整个事务将终止并回滚。

当 SET XACT_ABORT 为 OFF 时,有时只回滚产生错误的 Transact-SQL 语句,而事务将继续进行处理。如果错误很严重,那么即使 SET XACT_ABORT 为 OFF,也可能回滚整个事务。

编译错误(如语法错误)不受 SET XACT_ABORT 的影响。

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

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

  • 打赏
  • 举报
回复
igelf 2009-07-10
exec('insert into')
应该是属于语法错误.所以不起作用.

exec('insert into testtb(id)values(''d'')');
这个不属于语法错误,所以能全部回滚.

-------------------
那.SET XACT_ABORT 只对当前作用域起作用,这个好像不成立啊?

  • 打赏
  • 举报
回复
JonasFeng 2009-07-10
[Quote=引用 14 楼 chuifengde 的回复:]
SQL code1.SET XACT_ABORT 只对当前作用域起作用2.SET XACT_ABORT 只对运行时错误起作用,对编译错误不起作用insertinto testtb(id)values('d');这条语句运行时产生语法错误(属编译错误)所以不起作用
[/Quote]

正解。
  • 打赏
  • 举报
回复
csdyyr 2009-07-10
[Quote=引用 15 楼 igelf 的回复:]
TO:13楼.
刚才又测试了下.
sql2000确实不行.
sql2005能全部回滚.

[/Quote]
确实有这个区别。参考14楼。
  • 打赏
  • 举报
回复
igelf 2009-07-10
TO:13楼.
刚才又测试了下.
sql2000确实不行.
sql2005能全部回滚.
  • 打赏
  • 举报
回复
chuifengde 2009-07-10
1.SET XACT_ABORT 只对当前作用域起作用
2.SET XACT_ABORT 只对运行时错误起作用,对编译错误不起作用 insert into testtb(id)values('d');这条语句运行时产生语法错误(属编译错误)所以不起作用
  • 打赏
  • 举报
回复
csdyyr 2009-07-10
[Quote=引用 12 楼 igelf 的回复:]
确认.
[/Quote]

CREATE TABLE testtb(id int)
go
SET XACT_ABORT ON
BEGIN TRAN
insert into testtb(id) values(1);
exec('insert into');
COMMIT TRAN
go
select * from testtb
/*
id
-----------

(0 row(s) affected)
*/

drop table testtb
  • 打赏
  • 举报
回复
igelf 2009-07-10
确认.
  • 打赏
  • 举报
回复
csdyyr 2009-07-10
[Quote=引用 8 楼 igelf 的回复:]
哦.确实能回滚.
下面这样是不能正常回滚的.
SQL codeSET XACT_ABORTONBEGINTRANinsertinto testtb(id)values(1);exec('insert into');COMMITTRAN
[/Quote]
你真的确认?
  • 打赏
  • 举报
回复
htl258_Tony 2009-07-10
if @@error <>0 
begin
rollback tran
raiserror('唤起错误提示',16,1)
end
  • 打赏
  • 举报
回复
sdhdy 2009-07-10
[Quote=引用 5 楼 igelf 的回复:]
全部动态?
你们都这么写的吗.

还有我如果定义一个全部变量.
每次操作语句后面跟上.
if @@error <>0
Set @iserror=1;

在最后的时候判断
if @iserror=1
rollback tran
else
COMMIT TRAN

这样的话.如果有很多操作语句.
如果第一条操作语句出错了.
下面的照样能执行吧.
[/Quote]
应该会的,一般出错的时候我们还会加一个RAISERROR()语句,以利于前台捕捉这个错误。
  • 打赏
  • 举报
回复
igelf 2009-07-10
哦.确实能回滚.
下面这样是不能正常回滚的.

SET XACT_ABORT ON
BEGIN TRAN
insert into testtb(id) values(1);
exec('insert into');
COMMIT TRAN
  • 打赏
  • 举报
回复
igelf 2009-07-10

你真的确认下面能全部回滚?

SET XACT_ABORT ON
BEGIN TRAN
insert into testtb(id) values(1);
exec('insert into testtb(id)values(''d'')');
COMMIT TRAN
  • 打赏
  • 举报
回复
sdhdy 2009-07-10
一般都要这么写的,简单的办法貌似没有:
if @@error <>0
begin
rollback tran
return
end
  • 打赏
  • 举报
回复
igelf 2009-07-10
全部动态?
你们都这么写的吗.

还有我如果定义一个全部变量.
每次操作语句后面跟上.
if @@error<>0
Set @iserror=1;

在最后的时候判断
if @iserror=1
rollback tran
else
COMMIT TRAN

这样的话.如果有很多操作语句.
如果第一条操作语句出错了.
下面的照样能执行吧.
  • 打赏
  • 举报
回复
SQL会认为动态语句与非动态语句不在同一个作用域是这个问题产生的原因。
  • 打赏
  • 举报
回复
csdyyr 2009-07-10
--前两种写法可以全部回滚的。
CREATE TABLE testtb(id int)
go
SET XACT_ABORT ON
BEGIN TRAN
insert into testtb(id) values(1);
insert into testtb(id)values('d');
COMMIT TRAN
go
select * from testtb
/*
id
-----------

(0 row(s) affected)
*/
SET XACT_ABORT ON
BEGIN TRAN
insert into testtb(id) values(1);
exec('insert into testtb(id)values(''d'')');
COMMIT TRAN
go
select * from testtb
/*
id
-----------

(0 row(s) affected)
*/
drop table testtb
  • 打赏
  • 举报
回复
要动态的话,全部动态

exec('
SET XACT_ABORT ON
BEGIN TRAN
insert into testtb(id) values(1);
insert into testtb(id)values(''d'');
COMMIT TRAN
')
  • 打赏
  • 举报
回复
加载更多回复
相关推荐
最新单片机仿真 独立式键盘调时的数码时钟实验 最新单片机仿真 独立式键盘调时的数码时钟实验最新单片机仿真 独立式键盘调时的数码时钟实验最新单片机仿真 独立式键盘调时的数码时钟实验最新单片机仿真 独立式键盘调时的数码时钟实验最新单片机仿真 独立式键盘调时的数码时钟实验最新单片机仿真 独立式键盘调时的数码时钟实验最新单片机仿真 独立式键盘调时的数码时钟实验最新单片机仿真 独立式键盘调时的数码时钟实验最新单片机仿真 独立式键盘调时的数码时钟实验最新单片机仿真 独立式键盘调时的数码时钟实验最新单片机仿真 独立式键盘调时的数码时钟实验最新单片机仿真 独立式键盘调时的数码时钟实验最新单片机仿真 独立式键盘调时的数码时钟实验最新单片机仿真 独立式键盘调时的数码时钟实验最新单片机仿真 独立式键盘调时的数码时钟实验最新单片机仿真 独立式键盘调时的数码时钟实验最新单片机仿真 独立式键盘调时的数码时钟实验最新单片机仿真 独立式键盘调时的数码时钟实验最新单片机仿真 独立式键盘调时的数码时钟实验最新单片机仿真 独立式键盘调时的数码时钟实验最新单片机仿真 独立式键盘调时的数码时钟实验最新单片机仿真 独立式键盘调时的数码时钟实验最新单片机仿真 独立式键盘调时的
发帖
MS-SQL Server
加入

3.3w+

社区成员

MS-SQL Server相关内容讨论专区
申请成为版主
帖子事件
创建了帖子
2009-07-10 09:26
社区公告
暂无公告