如果在一组嵌套事务的任意级别执行没有 transaction_name 参数的 ROLLBACK WORK 或 ROLLBACK TRANSACTION 语句,那么它将回滚所有嵌套事务,包括最外部事务。作如下修改再试试:  begin tran tran1
  exec @res= pro_code @code
  if @res=1
    commit tran tran1
  else
    rollback tran tran1

解决方案 »

  1.   

    当 CURSOR_CLOSE_ON_COMMIT 设置为 ON 时,ROLLBACK 关闭但不释放所有打开的游标。
    当 CURSOR_CLOSE_ON_COMMIT 设置为 OFF 时,ROLLBACK 不影响任何打开的同步 STATIC 或 INSENSITIVE 游标,也不影响已完全填充的异步 STATIC 游标。将关闭但不释放任何其它类型的打开的游标。你可以改变你的游标类型或者将游标包含在事务中
      

  2.   

    libin_ftsafe(子陌红尘) :
    我试过了你的如下方法,无效:
      begin tran tran1
      exec @res= pro_code @code
      if @res=1
        commit tran tran1
      else
        rollback tran tran1
    ---------------------------------
    lh1979(rocket) :
    当 CURSOR_CLOSE_ON_COMMIT 设置为 ON 时,ROLLBACK 关闭但不释放所有打开的游标。
    你说的这点有错误,帮助中说是提交时是否关闭游标,所以应改成如下:
    当 CURSOR_CLOSE_ON_COMMIT 设置为 ON 时,COMMIT   关闭但不释放所有打开的游标。注意:这个选项是在事务提交commit时游标是否关闭。数据库默认是OFF,也就是commit后游标不关闭。
    和我说的问题不同,我是在commit时正常,也就是不关闭游标,但rollback后游标被关闭。
    ---------------------------------
    我的问题题目写的很清楚,错误出在:事务回滚rollback后,游标被关闭。要找个方法使rollback后,游标不被关闭,这样程序才能继续执行。
      

  3.   

    lh1979(rocket)的说反了,应该是:当 CURSOR_CLOSE_ON_COMMIT 设置为 OFF 时,ROLLBACK 关闭但不释放所有打开的游标。--下面是联机帮助上的原文:
    SET CURSOR_CLOSE_ON_COMMIT
    The SET CURSOR_CLOSE_ON_COMMIT statement sets all cursors on a connection to automatically close when a COMMIT TRANSACTION or a ROLLBACK TRANSACTION statement is issued.Syntax
    SET CURSOR_CLOSE_ON_COMMIT { ON | OFF };Arguments
    ON Specifies closing all cursors on a connection when a COMMIT TRANSACTION or a ROLLBACK TRANSACTION statement is issued.OFF (default)Specifies that the calling application is required to close each cursor on a connection when a COMMIT TRANSACTION or a ROLLBACK TRANSACTION statement is issued.Res
    You can use the SET CURSOR_CLOSE_ON_COMMIT command for standard and browse cursors.
      

  4.   

    --下面是测试:--测试表
    create table table1(code int)
    insert table1 select 1
    union  all    select 2
    union  all    select 3create table table2(id int,name nvarchar(20))
    insert table2 select 1,'aa'
    union  all    select 1,'bb'
    union  all    select 2,'cc'
    union  all    select 3,'dd'
    go--测试的存储过程
    create proc pro_code
    @code int
    as
    update table2 set name=name+'_更新' where id=@code
    if @code=2
    return 0
    else 
    return 1
    go--更新测试
    --set CURSOR_CLOSE_ON_COMMIT on  --如果设置为这个,则执行结果会报错
    set CURSOR_CLOSE_ON_COMMIT off   --默认值
    declare cur1 cursor fast_forward for
    select code from table1
    declare @code varchar(9)
    declare @res varchar(9)
    open cur1
    while 1=1
    begin
      fetch next from cur1 into @code
      if @@fetch_status<>0 break
      begin tran
      exec @res= pro_code @code
      if @res=1
        commit tran
      else
        rollback tran
    end
    close cur1
    deallocate cur1
    set CURSOR_CLOSE_ON_COMMIT off
    go--显示结果
    select * from table2
    go--删除测试
    drop table table1,table2
    drop proc pro_code
    /*--测试结果id          name                 
    ----------- -------------------- 
    1           aa_更新
    1           bb_更新
    2           cc
    3           dd_更新(所影响的行数为 4 行)
    --*/
      

  5.   

    发现奇怪问题了:
    原来在sql7.0中执行报错以上错误。
    而sql2000里执行是不报错的。 zjcxc(邹建)大侠,你一定是在sql2000环境测试的吧。而数据库参数CURSOR_CLOSE_ON_COMMIT 默认设置为 OFF 。
    我的sql7.0和sql2000数据库也都是OFF,没有改动过。
    所以问题不是出在这里!
    正确解释:
    当 CURSOR_CLOSE_ON_COMMIT 设置为 OFF 时,COMMIT或ROLLBACK 关闭但不释放所有打开的游标。
      

  6.   

    还有,zjcxc(邹建)大侠:
    我的存储过程和你测试用的几乎一样,只是简单的UPDATE,未使用事务。create proc pro_code
    @code int
    as
    update table2 set name=name+'_更新' where id=@code
    if @code=2
    return 0
    else 
    return 1
    go
      

  7.   

    我是sql2000中测试的,sql7没有测试环境
      

  8.   

    zjcxc(邹建):
    你认识有sql7环境的高手吗?帮忙测试解决一下吧!
    这个问题有点郁闷!
    我工作环境是sql7的数据库,调试程序的sql2000。
    所以我必须在sql7中运行这个程序。
    偏偏这个问题就是在sql7中才报错!对了,还有我的sql7是winnt4.0下的7.00.623。没装任何补丁!
    也希望有哪个高手能帮忙解决此问题!多谢!
      

  9.   

    书上说:
    CURSOR_CLOSE_ON_COMMIT当设置为 ON 时,在提交事务时,所有打开的游标都将自动关闭。默认情况下,此设置为 OFF,并且游标仍然在各事务边界间保持打开状态,仅当连接关闭或被显式关闭时,才会关闭游标。连接级设置(使用 SET 语句设置)替代 CURSOR_CLOSE_ON_COMMIT 的默认数据库设置。默认情况下,当连接到 SQL Server 时,ODBC 和 OLE DB 客户端发出连接级 SET 语句,以将会话的 CURSOR_CLOSE_ON_COMMIT 设置为 OFF。
      

  10.   

    hglhyy(查無此人) :
    老兄你写的是什么意思啊?
    我之前情况都说明了,我数据库CURSOR_CLOSE_ON_COMMIT 是默认设置OFF
    问题不在此。而且我说的问题,相同的程序在sql2000中执行正常,但在sql7中执行报错。我用的是正版sql7,可惜一年的免费服务已经过期了,向微软问任何问题都要另付费!-_-|||
      

  11.   

    关注中,可惜我没有SQL7
    不过我想是否可以用这样的折冲方法。
    在你在检测到错误时,就不要去关闭游标了。因为你都知道,游标已经管了。
    只是在提交了事务后,才去关闭游标。
      

  12.   

    检测到错误时,只是做了必须的事务回滚。我并没有关闭游标。是事务回滚时自动关闭的游标。我想不应该是sql7.0的bug吧?还是应该有什么参数可以控制,只是找不到!有sql7.0的高手吗?帮查查在sql7.0中,如何能让事务回滚时不关闭游标?