有三张表A、B、C
A(a1,a2.....)
B(b1,b2.....)
C(c1,c2.....)
其中a1为自动增长类型.
现在准备往表A中插入一条数据后,取得a1的值,再往表B、表C中插入数据,其中b1,c1的值为a1.
更新时也是按照a1、b1、c1等于某一个数,然后同时更新这三张表。
因为这三张表字段很多,所以用存储过程要写很长的参数列表(我对存储过程不是很熟)。
现在我想问的是,有什么办法能保证插入数据时,要么三张表都插入成功,要么就全部都不插入;更新时也是一样,要么三张表同时更新成功,要么就全部不更新。
谢谢大家了!

解决方案 »

  1.   

    ODBC SDK方法:
    SQLRETURN rc;
    rc=SQLSetConnectAttr(hdbc, SQL_ATTR_AUTOCOMMIT, (SQLPOINTER)SQL_AUTOCOMMIT_OFF, SQL_IS_INTEGER);rc=SQLExecDirect(hstmt, (SQLTCHAR *)TEXT("INSERT INTO A(,,,) VALUES(,,,)", SQL_NTS);
    if(rc!=SQL_SUCCESS_WITH_INFO && rc!=SQL_SUCCESS) goto Label_ErrExit;
    rc=SQLExecDirect(hstmt, (SQLTCHAR *)TEXT("INSERT INTO B(,,,) VALUES(,,,)", SQL_NTS);
    if(rc!=SQL_SUCCESS_WITH_INFO && rc!=SQL_SUCCESS) goto Label_ErrExit;
    rc=SQLExecDirect(hstmt, (SQLTCHAR *)TEXT("INSERT INTO C(,,,) VALUES(,,,)", SQL_NTS);
    if(rc!=SQL_SUCCESS_WITH_INFO && rc!=SQL_SUCCESS) goto Label_ErrExit;rc=SQLEndTrans(SQL_HANDLE_DBC, hdbc, SQL_COMMIT); //全部成功
    return TRUE;Label_ErrExit:
    rc=SQLEndTrans(SQL_HANDLE_DBC, hdbc, SQL_ROLLBACK);//不全成功, 则回退至更新前状态
      

  2.   

    create procedure insertData @a1 int, @a2 int, @a3 int ....
    as declare @id int
     begin trans t1
     insert into A(a1,a2,a3...)values(@a1,@a2,@a3...)
     if @@error != 0
        goto err
     set @id=@@rowcount insert into B(.....)
     if @@error != 0
        goto err insert into C(....)
     if @@error != 0
        goto err commit trans t1
     returnerr:
     rollback trans t1
      

  3.   

    TO chehw:
       谢谢你的帮助.碰巧我是用VC+ADO来操作SQL SERVER 2000,有没有关于ADO这方面的?
    其实是这样的,当用户按“插入”按钮后,程序将会取得大概100个左右的数据,现准备将这些数据插到三张表里;插入数据时,要么三张表同时插入成功,要么取消本次插入操作。更新操作也是一样。
      希望能得到更多大侠的赐教,谢谢!
      

  4.   

    ADO provides the following methods for controlling transactions: BeginTrans, CommitTrans, and RollbackTrans. Use these methods with a Connection object when you want to save or cancel a series of changes made to the source data as a single unit.
      

  5.   

    TO jun_01
        谢谢你的帮助。是这样的,我这三张表字段比较多(差不多100个),如果写成存储过程,参数列表会很长很长,还有没有其他方法?
      

  6.   

    TO chehw:
        BeginTrans, CommitTrans, and RollbackTrans.这些我都可以用。现在主要是我的表字段比较多,如果写一个带100个参数的存储过程,会不会大了点呢?
      

  7.   

    非存储过程的2个办法
    1,构造insert into sql语句,但是构造的时候也是很体力的
    2,使用parameter对象和parameters集合。用command对象来执行insert into 语句
    insert into table(f1,f2,f3....) values(?,?,?,...)有多少个参数就要写多少个?号
    而且parameters的参数类型和顺序一定要和sql语句里的一致。也比较体力。至于事务的问题,connection对象有一下几个方法
    BeginTrans — 开始新事务。 
    CommitTrans — 保存更改并结束当前事务。它也可能启动新事务。 
    RollbackTrans — 取消当前事务中所做的更改并结束事务。它也可能启动新事务这样能够保证你的sql语句运行后,在committrans之前不会真正提交
      

  8.   

    TO vieri_ch:
       谢谢你的帮助。我现在是用connection的EXECUTE方法来操作数据库的。
     对于你说的非存储过程的方法1,是不是这样执行:
     1、调用Cconnection的BeginTrans方法
     2、执行相关的数据库操作
     3、判断操作是否成功,若成功,则调用Cconnection的CommitTrans方法,若不成功,则调用
      Cconnection的RollbackTrans方法
     也就是说,所有对数据库的操作都是在VC中用语句来执行,无须额外写存储过程?
     还有,你说的方法2中,是不是还要写一个存储过程?
     有没有具体的源代码?有的话,麻烦贴一下。呵呵,本人比较笨。
      

  9.   

    你说得方法1的理解是正确的,不需要些存储过程方法2和方法1差不多对事务处理的方式一样,但是使用command来执行sql语句而不是存储过程。并且执行之前构造相关参数。与方法1的不同在于
    insert into table(f1,f2,f3....) values(?,?,?,...)你可以把这个语句写到配置文档中,并指出参数的类型。在程序运行时可以根据这个语句来动态确定有多少个参数和类型并且动态构造parameters参数集合,并执行语句。比较灵活一些。如果你不需要这样的灵活性,只用方法1就够了
      

  10.   

    TO vieri_ch:
       再次谢谢你的帮助。对于用command对象来执行存储过程,我知道的是parameters参数集合中定义的参数顺序和类型都要和存储过程中定义的要一致。
       能否详细说说你在10楼回复中,最后一段文字的意思?或者给个教程连接之类的?我知道这些知识在书上是很难找到的。
      谢谢了!
      

  11.   

    通常的用法都是
    parameter+command+存储过程来用,其实也可以parameter+command+SQL语句。那段文字的描述的意思我会提供一些代码来说明,不过可能时间会推后一些。
      

  12.   

    我也是想用parameter+command+存储过程来做的,奈何表的字段太多了,才想用其他的方法来实现。
      谢谢vieri_ch热心的帮助,期待你精彩的回复!