您的位置:程序门 -> vb -> 基础类



用 insert into 语句新增保存了一条记录,如何获取这条新增记录的自动编号字段的内容?


[收藏此页] [打印本页]选择字色:背景色:字体:[][][]


用 insert into 语句新增保存了一条记录,如何获取这条新增记录的自动编号字段的内容?[已结贴,结贴人:xieyudada]
发表于:2008-01-17 12:49:57 楼主
        我原本用的是access2000,后听说2000不支持事务处理,现已经改为access2003版本了。
          我现在在做销售出库单保存按扭中的事件过程,此过程中,在保存完主表信息后,需要马上提取此条记录的自动编号内容给从表保存时用。原来试着用   addnew   方法(ado)和   update   方法(ado)来保存记录,虽然此方法能马上返回刚才所新增记录的自动编号,但这种方法绝对的不理想,在此就不多说了,现在改成用   insert   into   语句来保存。但用insert   into   语句来保存完成后,不知道在同一个过程中怎样能马上理想的提取到刚刚所保存的这条记录自动编号字段的内容。
        我曾用insert   into   语句保存完后,再用select   语句查询主表信息,再提取此主表的最后一条记录的自动编号字段内容来用。可用这种方式,姑且先不考虑网络联机多用户操作的因素,仅单机使用,在测试了多遍后,就曾出现了一次错误,错误的提取了上一张单子的id,而非刚刚保存的这张单子的id,很吓人啊,可见此方法要枪毙了。
        我搜索网上的相关贴子,有这么个例句(insert   into   test(a,b)   values('asd','ddd')     select   @@identity     as     id),似乎可以实现这个目的,但就在此贴的下楼就有一个朋友说“微软建议:最好少用@@identity,而用scope_identity或identity_current来代替”,不知道是什么意思,让我心里又有些不着落了。
        我试着将自己的insert   into   语句改成这样写:
set   rs3   =   cnn.EXECute   ("insert   into   spxsb(ckzlid,wsttzlid,khzlid,xsbbh,qsbh,fphm,yfpsfxf,djxfdr,djxfsj,rq,hjje,bz,zdr)values   "   &   _
                "("   +   str(text1.text)   +   ","   +   str(text2.text)   +   ","   +   str(text3.text)   +   ","   &   _
                "'"   +   trim(right(left(trim(label5.caption),   15),   11))   +   "',"   &   _
                "'"   &   text9.text   &   "',"   &   _
                "'"   &   text12.text   &   "',"   &   _
                ""   &   iif(check1.value   =   0,   "0",   "   -1   ")   &   ","   &   _
                "'"   &   label7.caption   &   "',"   &   _
                ""   &   iif(not   isdate(label8.caption),   "null",   "#"   &   label8.caption   &   "#")   &   ","   &   _
                ""   &   iif(not   isdate(dtpicker1.value),   "null",   "#"   &   dtpicker1.value   &   "#")   &   ","   &   _
                ""   &   iif(trim(mshflexgrid2.textmatrix(0,   3))   =   "",   "null",   trim(mshflexgrid2.textmatrix(0,   3)))   &   ","   &   _
                "'"   &   iif(trim(text8.text)   =   "",   null,   trim(text8.text))   &   "','"   +   trim(label6.caption)   +   "')"   ,   i)
        可警告说:“sql语句的结束位置缺少分号(;)”。因为本人是个新手,仅凭此贴中的只言片语还无法写出完整的sql句子,只好又到这里求教来了。不知道走过路过的各位前辈高手们,你们是怎么实现这个目的的呢?
发表于:2008-01-17 14:08:021楼 得分:0
晕access2000怎会不支持事务?
@@identity   是sql   server   的用法
access我一般用记录集对象(其中id字段为自动编号)
rst.add
rst!字段2="22"
rst.update
debug.print   rst!id     这时候就是新值

发表于:2008-01-17 14:09:422楼 得分:1
在插入之后再读取本条记录
或者
在插入之前先读取最后一条记录,然后根据自动增量计算出自动编号的值
发表于:2008-01-17 14:33:083楼 得分:0
    我又找到了一个贴子,示例如下:

    jet4.0以后支持select   @@identity语句,这条语句执行后会返回执行这条语句的connection对象最近一次插入的记录中的自动编号字段的值。请看例程:  

    cnn.EXECute   "insert   into   goods   (name,description)values   (   '新商品1   ',   '新商品描述1   ')   "  
    dim   rst   as   adodb.recordset  
    set   rst=new   adodb.recordset  
    rst.open   "select   @@identity   "  
    msgbox   rst(0)       '这里rst(0)即为新记录的自动编号字段的值

    我试着照样子,引用到我的事件中执行后,倒也能顺利的执行下去,并不弹出警告,似乎语句写的并没错,可执行后返回的值始终是0,不知道怎么会事?我想如果当真select   @@identity语句是这个贴子说明的这样,那可太妙了,那无论如何也要将它学会喽,还请各位高手不吝赐教,多帮忙了!
发表于:2008-01-17 17:07:564楼 得分:0
        我用access数据库,select   @@identity   语句试来试去都是不行,可能yangzn76兄说的是对的,这个语句只适用于sql   server数据库。那么我暂时就不钻牛角尖了,采用junki兄的办法。
        那么,我又遇到了一个问题,再次请教各位,是关于事务处理的。
        还是在这个销售单保存按扭事件中。我放入了事务处理语句。
        首先,如果不放事务处理语句,这个过程执行的没问题,也就是说各条sql语句写的都是对的。可是,加上事务处理后,在执行cnn.committrans'(提交事务)后,就会跳到出错块(照理说不用跳的),在执行cnn.rollbacktrans'(错误回滚)时就弹出警告“试着不先使用begintrans而提交或退回事务。”,不知道是怎么会事?请高手们指点一下,谢谢!
发表于:2008-01-17 18:42:085楼 得分:0

在执行sql前用cnn.begintrans开始一个事务,
在执行sql后用cnn.committrans提交一个事务
如果出错用cnn.rollbacktrans回滚。
发表于:2008-01-17 18:45:206楼 得分:0
access   数据库应该是单机版应用吧?

你出错的原因是,   sql   语句是发送给   jet   数据库引擎去执行的,因此和   vb   代码是异步的。也就是说,你读自增编号时不能保证新的插入已经完成。
如果你是单机版,这个问题好解决。你只需在   cn.EXECute   语句中加上   recordsaffected   属性,就可以使插入完成后才继续执行后续语句:

dim   n   as   long
cn.EXECute   strsql,   n

......

如果多用户版就比较麻烦。因为   access   库不能锁表,只能锁记录。你无法保证所读记录是你新插入的。
发表于:2008-01-17 20:00:157楼 得分:0
      先回复草上飞兄,我想我的事务处理语句正是如您这般写的。
      of123兄,如您所说,我可不可以这样理解:
      1、因为access数据库是通过   microsoft.jet.oledb.4.0   数据库引擎去执行数据库操作的,所以,不管2000、2003,或是更高版本,百分百的都不能执行数据库事务处理语句(cnn.begintrans开始一个事务;cnn.committrans提交一个事务;cnn.rollbacktrans回滚。);
      2、access数据库,只能锁记录,不能锁表。功能欠缺;
      3、综上所述,总之一句话,access数据库不适合做为多用户版的应用程序的数据库,只适合做单机版的。
      of123兄,请赎我赘言,我这个理解对吗?如果我理解的没错,那么请教一下,如果我想做多用户应用程序的话(企业进销存管理软件),应该选择什么数据库比较好呢?就是此数据库技术目前已经比较成熟,而且相关的书籍教材(中文版的)等也比较丰富的。您看,是不是sql   server数据库?
发表于:2008-01-18 08:27:178楼 得分:2
1.   access   可以处理事务。
2.   access   不是服务型数据库,而是文件型,主要是为单用户应用设计的。当然,它可以支持多用户。
3.   进销存这类应用,一般不会大量用户并发访问,用   access   应该可以。但最好设计成   c/s   架构,由   server   端来访问数据库。
发表于:2008-01-18 10:04:159楼 得分:1
在准备数据插入之前取得目前数据库中id字段的最大值;
最大值加1就是下一条记录的id值了,可以用这一数据进行必要的操作。
设置成自动增长型时在插入记录时通常不太在意下一条记录的id号,这样做是为了先行明确。
发表于:2008-01-18 10:34:4810楼 得分:0
        哎呦我的娘咧!本来,听您那样说,我差不多是绝望了,睡了一晚上后也是绝望打算了。可现在又听您这么说,我这心呦,又给勾引的痒痒的啊!那么,既然access这么争气呼,岂有不拿下之理,of123兄,小弟这就要仰仗您多多指教了,你给个qq或邮箱,咱们交个朋友怎么样?那我可荣幸之至了!我的qq是76950746。
          回正题。
          一:从网上贴子上看来的,听说事务处理有3种形式,1、写在存储过程中,我不太懂,access能做这种形式的事务处理吗?2、直接写在vb的代码中,这个我差不多应该算有点懂了吧,目前正在尝试,正如我上楼所提问的,为什么会弹出警告“试着不先使用begintrans而提交或退回事务。”,of123兄您看这是怎么回事呢?3、跨多服务器事务处理,这个目前我就不奢望懂了。
        of123兄,如果access能在存储过程中事务处理的话,我们应该怎么写这种事务处理?我们有这个必要采用这种方式吗?这种方式相对于第2种方式有什么好处呢?一般都是在什么情况下采用这种方式来事务处理呢?
        二:您说让我最好能设计成   c/s   架构,由   server   端来访问数据库。不怕您见笑,我真是孤陋寡闻啊,对这个一点也没感念呢。我心痒难耐,求知若渴,能不能请您耐心的跟我说一下,c/s   架构是什么概念?用access数据库的话,具体应该怎么设计成   c/s   架构,由   server   端来访问数据库呢?小弟拜谢了!
发表于:2008-01-18 12:36:1511楼 得分:1
建议你不要这样设计,你这样的需求用自定义id号更好
事务处理由ado支持,好象和什么数据库无关吧?当然许多数据库,特别是提供网络服务的数据库自身也提供事务处理
发表于:2008-01-18 18:28:5812楼 得分:0
插入语句执行之后的第一条语句使用@@identity
是支持access的,一般用这个就行了
发表于:2008-01-18 19:53:4313楼 得分:0
    怎么?access数据库真的支持@@identity语句吗?本来我是很兴奋的,有这样好东西那还不妙极。我也曾找到示例,示例如下:

    cnn.EXECute   "insert   into   goods   name,description)   values   (   '新商品1   ',   '新商品描述1   ')   "  
    dim   rst   as   adodb.recordset  
    set   rst   =   new   adodb.recordset  
    rst.open   "select   @@identity   "  
    msgbox   rst(0)       '这里rst(0)即为新记录的自动编号字段的值

      我照着样子测试了,可返回的值始终是0。再接着找贴子。有人说需要使用adox的catalog对象创建,其方法是:
      cat.create   "provider=microsoft.jet.oledb.4.0;data   source=c:\newjet4.mdb;   "  
      这个我就不能理解了,ado不都是用adodb.connection对象创建连接的吗?唉,总之,如果真有懂的高手的话,您就帮人帮到底,给说个具体的,别勾引的我心里痒痒的,可又一知半解的弄不懂,那可真难受呦!
发表于:2008-01-18 21:03:4714楼 得分:0
晕,使用方法的问题啊

谁说不可以的?

cnn.EXECute       "insert       into       goods       name,description)       values       (       '新商品1       ',       '新商品描述1       ')       "  

dim       rst       as       adodb.recordset      
        set       rst       =       new       adodb.recordset      
        rst.open       "select       @@identity   as   myid     from     goods"    

这样就可以了,跟sql   server的写法不一样
发表于:2008-01-18 21:06:5915楼 得分:0
关键是一插入数据就引用"select   @@identity   from   [表]",要写具体表的
发表于:2008-01-18 21:42:4516楼 得分:0
        这为兄弟,我照着你提供的样式,试了一下,还是不行嘛!真的郁闷死了,也不知道是我特别苯还是怎么的。我将我的代码贴出来,请您再帮忙看看啊!
    cnn.EXECute   ("insert   into   spxsb(ckzlid,wsttzlid,khzlid,xsbbh,qsbh,fphm,yfpsfxf,djxfdr,djxfsj,rq,hjje,bz,zdr)values   "   &   _
        "("   +   str(text1.text)   +   ","   +   str(text2.text)   +   ","   +   str(text3.text)   +   ","   &   _
        "'"   +   trim(right(left(trim(label5.caption),   15),   11))   +   "',"   &   _
        "'"   &   text9.text   &   "',"   &   _
        "'"   &   text12.text   &   "',"   &   _
        ""   &   iif(check1.value   =   0,   "0",   "   -1   ")   &   ","   &   _
        "'"   &   label7.caption   &   "',"   &   _
        ""   &   iif(not   isdate(label8.caption),   "null",   "#"   &   label8.caption   &   "#")   &   ","   &   _
        ""   &   iif(not   isdate(dtpicker1.value),   "null",   "#"   &   dtpicker1.value   &   "#")   &   ","   &   _
        ""   &   iif(trim(mshflexgrid2.textmatrix(0,   3))   =   "",   "null",   trim(mshflexgrid2.textmatrix(0,   3)))   &   ","   &   _
        "'"   &   iif(trim(text8.text)   =   "",   null,   trim(text8.text))   &   "','"   +   trim(label6.caption)   +   "')"),   i
    dim   rst   as   adodb.recordset
    set   rst   =   new   adodb.recordset
    rst.open   "select   @@identity   as   myid   from   spxsb   ",   cnn,   adopenstatic,   adlockoptimistic
    msgbox   rst.fields("myid")     '这里rst(0)即为新记录的自动编号字段的值。

        您看,我那里写的不对呢?都照着你的样式写的了,可   msgbox   函数返回的值依然是0。急死了。
发表于:2008-01-18 22:51:2617楼 得分:0
光标类型用键集
发表于:2008-01-18 23:42:1618楼 得分:0
      这位兄弟,我试过了,还是不行耶。我是仅向前、键集、动态、静态等类型游标都试过了,可返回的值依然都是0。真不好意思啊,让你多费心了,如果真能学会这个的话,我会很感激你的。当然,现在也很感激你的。呵呵!

        dim   rst   as   adodb.recordset
        set   rst   =   new   adodb.recordset
        rst.open   "select   @@identity   as   myid   from   spxsb   ",   cnn,   adopenkeyset,   adlockoptimistic
        msgbox   rst.fields("myid")
发表于:2008-01-18 23:56:1319楼 得分:0
对了,问一句,你表里头有没有自动编号?有没建立主键和索引?还有primarykey是不是升序,如果为降的话肯定是0,因为第1之前就是0
发表于:2008-01-18 23:59:4120楼 得分:0
还没睡哪,可真让您费心了。干脆,咱交个朋友,上qq好吗?我把我的整个工程打包给您看得了。好吗?
发表于:2008-01-19 00:06:0121楼 得分:0
我是vb6.0   +   access2000,商品销售表,就是spxsb   表中绝对的有自动编号字段,是主键,有索引,升序。
如果您有意加我qq的话,我的qq号是76950746
发表于:2008-01-19 00:16:0022楼 得分:15
29628988
发表于:2008-01-22 23:02:3423楼 得分:0
        真心的感谢这位喜欢抽烟的兄弟,是他给予了耐心的帮助,现在将他提供的例程贴在这里,供需要的朋友参考。

      dim   rss   as   recordset
      set   rss   =   new   recordset
      rss.open   "insert   into   zhzl(mc)   values('bbbbbbbbbbbbbb')",   cnn,   adopenkeyset,   adlockpessimistic     '键集类型游标,保守式锁定
      rss.open   "select   @@identity   from   zhzl"
      msgbox   "新增的id为:"   &   rss.fields(0).value

      这段代码绝对是通得过的,也就是说   @@identity   语句是适用于   access2000   数据库的。另外补充几句我的心得:要用   @@identity   语句的话,新增记录时得用   open   方法,后面的参数应该得用键集。
      我以前也是喜欢用   open   方法的,但因为我不懂的   open   方法后坠的两个参数的应用,我以前总是采用静态游标和开放式锁定,那样在执行sql的时候,程序总是在sql还未执行完毕的时候就已经去执行sql语句下方的代码了,这样困扰了我很长的一段时间。现在得到了   phenlit   兄弟的指导,总算让我茅塞顿开啊,现在采用键集和保守式锁定,问题一切搞定。
      晓事后,既然可以用   open   方法了,那么我原来用   update   方法(ado)来保存数据,能更方便的得到刚才新建记录的自动编号字段内容的。现将我的代码贴出,给朋友们借鉴。

      dim   rs4   as   new   adodb.recordset
      if   rs4.state   <>   adstateclosed   then   rs4.close
      rs4.open   "select   *   from   cgjspycyb   where   gyszlid="   +   trim(text6.text)   +   "   order   by   cgjspycybid   asc",   cnn,   adopenkeyset,   adlockpessimistic     '键集,保守式锁定
      rs4.addnew     'addnew   方法(ado):为可更新的   recordset   对象创建新记录。
    rs4.fields("gyszlid")   =   text6     '供应商资料id
    rs4.fields("spzlid")   =   mshflexgrid1.textmatrix(mshflexgrid1.row,   6)     '商品资料id
    if   mshflexgrid1.textmatrix(mshflexgrid1.row,   7)   <>   ""   then   rs4.fields("hsyj")   =   mshflexgrid1.textmatrix(mshflexgrid1.row,   7)   else   rs4.fields("hsyj")   =   null
      rs4.update     'update   方法(ado):保存对   recordset   对象的当前记录所做的所有更改。
      mshflexgrid1.textmatrix(h,   4)   =   rs4.fields("cgjspycybid")     '将刚才所新建的记录自动编号字段内容读取到当前行的第4列。


快速检索

最新资讯
热门点击