有点似懂非懂。
第一个问题,用sql管理单号,这单号是自动生成的呢,还是由凭证得来的。可以说的详细一些。
还是先解决第二个问题吧。
我想你说是改进的话,应该代码错误是不大有的吧。
改进的方法:
     1。你可以这样,把事物处理部分的代码都作成存储过程,而不要放在前端,把回滚防在sql端来处理。代码这么多,可能会影响网络的流量。代码作成存储过程,维护起来,要方便的多。前端只要用一个sqlexec(handle,"exec procname")就行了。另外,你这端代码,应当在以后的使用中的改动可能性比较大,那样你也只要改动服务器的存储过程就行了。
  2。不要用循环,用sql语句来完成。比如你那段scan的代码。你可以用sql 语句。因为insert into tablename(field1,field2) select field1,field2 from table2在vfp中是不支持的。你可以把它作成存储过程,然后调用它。因为它基于集合处理,比scan的速度快的多,而且,代码也容易看的懂。在视图中移动指针很影响性能的。
  3。由于,你程序要实现的业务流程不是很清楚,从字符推测表的内容不大方便,所以不知道能否从流程上进行改善。
  4。第四个问题,你这个handle是哪来的,用的是spt还是远程视图。

解决方案 »

  1.   

    TO:liujianjun_(流星尔)
    第一:单号当然希望是SQL管理。自动生成。但是要做到年月日+单号
    第二:SQL的存储过成我没写过呀。(可以帮写一下吗?)
    第三:我开始是用远程视图但解决不了回滚问题。(后来改成SCAN的)
    第四:HANDLE=SQLCONNECT("Y1")谢谢!!!!!!!!
      

  2.   

    我举个例子。
     在sql server里选中数据库里stored proced,右键选新建,在里面写上
    create proc procname(自己定义) as
       begin
         insert into jcdmx(jcdh,ks_no,ckmc,lb,hpbm,hpmc,hpdw,jcsl,jcdj,jcje,jczk)   
         select jcdh,ks_no from jcdmx_c
       end
    客户端调用
       if sqlexec(handle,"exec procname")!=1
          messagebox("数据更新失败!")
        endif
      

  3.   

    事物处理这方面我也不大懂,一直没有好好地去学习一下。所以写的比较粗糙。
    你的连接我建议用字符串连接,因为,老是要建odbc数据源很麻烦。
      handle=sqlstringconnect("driver=sql server;server=servername;uid=客户机名;pwd=登录密码;database=数据库名")
    这样的话,连接比较有通用性
      

  4.   

    另外,如果更新的列不多的话,建议用spt代替远程视图。我发现远程视图更新数据的速度实在是不能忍受。所以,我能用spt的都用上了。实在字段太多,不想写代码的地方才用视图。
      至于单号,有两个办法,一个是前端更新单号的地方写程序,或者sqlserver段写存储过程,更好的方法是写触发器。我触发器不大熟,只会一点简单的。
      

  5.   

    SELE JCDMX_C
    SCAN
    SQLSTRINGS="INSERT INTO JCDMX (JCDH,KS_NO,CKMC,LB,HPBM,HPMC,HPDW,JCSL,JCDJ,JCJE,JCZK) VALUES ('"+ALLT(JCDMX_C.JCDH)+"','"+ALLT(JCDMX_C.KS_NO)
    SQLSTRINGS=SQLSTRINGS+"','"+ALLT(JCDMX_C.CKMC)+"','"+ALLT(JCDMX_C.LB)+"','"+ALLT(JCDMX_C.HPBM)+"','"+ALLT(JCDMX_C.HPMC)+"','"+ALLT(JCDMX_C.HPDW)
    SQLSTRINGS=SQLSTRINGS+"','"+ALLT(STR(JCDMX_C.JCSL,12,2))+"','"+ALLT(STR(JCDMX_C.JCDJ,12,2))
    SQLSTRINGS=SQLSTRINGS+"','"+ALLT(STR(JCDMX_C.JCJE,12,2))+"',"+ALLTRIM(STR(JCDMX_C.JCZK))+")"
    IF SQLEXEC(HANDLE,SQLSTRINGS)<1
    SQLEXEC(HANDLE,"ROLLBACK TRANSACTION")
    MESSAGEBOX('生效失败',16,'提示')
    RETU
    ENDIF
    ENDSCAN
    是不是这样呀??可是这样会快吗?写代码也烦死了.有没有跟好的办法???还有就是如果上面的"SQLSTRINGS"大于256字节时有什么好办法?
    我现在是用先INSERT再UPDATE分开两次写,是不是很笨呀?
      

  6.   

    不是不是。我把你上面的代码作成存储过程
    在sql server里找到你的数据库,然后展开,选中stored procedures,右键选new procedures
    然后写代码(它已替你写了一点,那段你可以不写)
    create proc proc1(我定义该存储过程名为proc1)
    as
      begin
        insert into jcdmx(jcdh,ks_no,ckmc,lb,hpbm,hpmc,hpdw,jcsl,jcdj,jcje,jczk)  
        select jcdh,ks_no,ckmc,lb,hpbm,hpmc,hpdw,convert(numeric (9,2),jcsl)as jcsl,convert(numeric (9,2),jcdj) as jcdj,convert(numeric (9,2),jcje) as jcje,convert(numeric (9,2),jczk) as jczk from jcdmx_c
      end然后,在vfp里写这段代码的地方先注释,改成如下代码:
    if sqlexec(handle,"exec proc1")!=1
       messagebox("生效失败!")
    endif
      

  7.   

    写错了,在convert()的地方,因为你要把金额,单价,进厂数量,jczk转换成字符型。
    全都换成convert(chr(width),fieldname),把width换成转换字段的宽度,fieldname换成要转换的字段。
    建议:进厂金额在数据库里不要,jczk不知道是什么,如果可以由计算得到也不要,因为只要有单价有数量,就有金额。进厂金额一般是在查询里用到。比如我今天要查进厂金额。那我只要在查询的地方写上select jcsl,jcdj,jcsl*jcdj as jcje from table.
      这样的话,你可以不处理这些字段,出错的可能性小。另外,最好不要把数值性专程字符性。
      

  8.   

    JCDMX_C
    是VFP本地的数据表呀.现在说的是上传的问题呀.
      

  9.   

    存储过成我明白了.只是在传数据的时候它好象用处不大吗?和写一条SQL一样的速度吧?
      

  10.   

    因为sql server支持insert into select from 的语法,你就可以直接把要插入的字段从另一个表里取出来,得到一个结果集,直接追加到要插入的表中。这样,你也就不必考虑sqlstring的长度了。
       你所说的先insert在update是怎么回事,我想用刚才的语句,你可以直接insert的
      

  11.   

    它和一条sql语句是有区别的。它第一次执行的时候和一条语句一样。以后就会快一些。因为sql server每次执行sql语句都要优化执行计划。存储过程再第一次执行后,已编译过,第二次执行时会快一些。当然,我主要还是从代码的优化上来考虑的。代码太多了,太杂了,看起来就累了。速度上记录数少的话,要明显的区别出速度,不大可能
      

  12.   

    或者,我觉得用vfp命令可能更简单一些,也说不定。
    不要用scan,直接用appe from tablename field1,field2 要转换类型的地方,你可以把服务器上的表改成数值型,每次都转换多麻烦
      

  13.   

    "因为sql server支持insert into select from 的语法,你就可以直接把要插入的字段从另一个表里取出来,得到一个结果集,直接追加到要插入的表中。这样,你也就不必考虑sqlstring的长度了。
      你所说的先insert在update是怎么回事,我想用刚才的语句,你可以直接insert的 "VFP的字段好象只支持256字节的吧?"SQLSTRINGS="INSERT INTO JCDMX (JCDH,KS_NO,CKMC,LB,HPBM,HPMC,HPDW,JCSL,JCDJ,JCJE,JCZK).........."这个SQLSTRINGS大于256字节怎么办?
      

  14.   

    "或者,我觉得用vfp命令可能更简单一些,也说不定。
    不要用scan,直接用appe from tablename field1,field2 要转换类型的地方,你可以把服务器上的表改成数值型,每次都转换多麻烦"JCDMX_C是VFP表.
    JCDMX是SQL表.怎么还可以用APPEN.快说一说怎么个用法...
      

  15.   

    sql表可以直接从vfp表appe from,就像两个vfp表操作一样。你应当是把vfp表的记录追加到sql表中吧
      

  16.   

    sql表可以直接从vfp表appe from,就像两个vfp表操作一样。你应当是把vfp表的记录追加到sql表中吧
      

  17.   

    例如:你上面的代码可以写成:
    sele jcdmx
    appe from path/jcdmx_c fields jcdh,ks_no……,当然,必须保证两个表中的字段名一样。
    不过用视图追加的话,可能速度可能更你现在的差不了多少。我不喜欢远程视图就是这一点,追加几条记录也要老半天。
      

  18.   

    TO:liujianjun_(流星尔)
    老大呀.JCDMX_C是VFP表.JCDMX是SQL表.
    哪就是说还是用我现在的办法了.(我现在就是用你说的办法在做了)
    视图会比SCAN加SQL语句慢吗?
    还用就是用视图数据是不可以加滚的。
    哪用SQL管理单号呢(也就是说自动生成单号,但前题是要做到年月日+单号.)
    2000112160001.2000112160002......2000112169999.
    这个怎么做得到。
      

  19.   

    对呀,你是不是要jcdmx_c中的数据追加到jcdmx表中,对吗。如果是的话,就可以用appe from了。反过来就不行。
      视图当然不会比scan慢,我只不过夸张了一点。
      

  20.   

    视图上的回滚我没有试过,但我想也应该是行的。你可以运用vfp的本地事物处理。(我没用过事物)。试试这样写
    begin tran
      sele jcdmx_c
      appe from paht/jcdmx
    end transql表可以用appe from从vfp表追加数据,但vfp表不能从sql表中用appe from 追加数据 。
      

  21.   

    视图上的回滚我没有试过,但我想也应该是行的。你可以运用vfp的本地事物处理。(我没用过事物)。试试这样写
    begin tran
      sele jcdmx_c
      appe from paht/jcdmx
    end tranVFP上的事务管理不了SQL的.我还加了SQL的事务也是不行呀.
    只要数据是上传了,不管你用VFP的回滚还是SQL的回滚都是无效.(你可以试一下)
    (sql表可以用appe from从vfp表追加数据,但vfp表不能从sql表中用appe from 追加数据 。)
    你的意思是不是SQL用远程视图,才可以用APPEN.
    VFP的APPEN 我用会用呀.只是不知道怎么样才可以在SQL上也用APPEN.
    SQL的INSERT我也有用....
      

  22.   

    单号,可能还是写个单号自动编号的程序好。比如今天新录进一个单号。
    你可以先索引一下,go bott得到编号,repl新进编号加一就行了。
    也可以先select max(bh) as max_bh from table
    max=max_bh
    然后repl 新进编号 with 年+月+日+allt(str(max+1)
    最好还是用触发器。不过触发器要sql高手帮忙了。
    对我来说有点难
      

  23.   

    你刚才说的回滚,可能是我那样做真的实现不了。那可能就真的要用存储过程了。或者要sqlexec调用了。
    至于appe from,很简单,你可以试试。把jcdmx_c做成远程视图,然后你appe from path/jcdmx fields jcdh,ks_no……
    也不一定要作成远程视图,也可以用spt的光标。
      

  24.   

    我用spt做appe from 的例子:
    do prg\link  &&调用程序建立连接if  jb>0 and sqlexec(jb,"")=1 &&测试连接有效性
        sqlexec(jb,"select gwg.sno,gwgje,qxns,wyjje,qdsj,gdh,rsda.xm,rsda.xb,wxgsbm.mc as gs_bm from rsda join gwg on;
        rsda.sno=gwg.sno join wxgsbm on wxgsbm.bh=rsda.gbbh","lsb")&&通过多表连接生成光标
    sqlexec(jb,"exec rsda_gs_bm","rsda") &&调用存储过程生成光标
    else
        messagebox("网络正忙或连接出错,请稍侯再试!")
        cancel
    endif
    sele lsb
    cursorsetprop("tables","gwg","lsb") &&设置临时表的更新目标表
    cursorsetprop("keyfieldlist",'sno',"lsb") &&设置临时表的关键字
    cursorsetprop("updatablefieldlist","sno,gwgje,qxns,wyjje,qdsj,gdh","lsb")&&设置临时表的更新字段
    cursorsetprop("updatenamelist","sno gwg.sno,gwgje gwg.gwgje,qxns gwg.qxns,wyjje gwg.wyjje,qdsj gwg.qdsj,gdh gwg.gdh","lsb") &&&用lsb中的相应字段更新 gwg表
    cursorsetprop("sendupdates",.t.,"lsb")&&设置为可更新
    cursorsetprop("wheretype",2)sele lsb
    appe from temp\gwg field name,xb &&temp\gwg为vfp表
    tableupdate(0,.t.)
      

  25.   

    to vfp_data:
       我给你的回滚解决了。发到你的信箱了
      

  26.   

    一点帮助:
    有关在VFP中使用SPT,不必全部这样将变量转成字符串再连接,在SPT中是可以使用变量的,格式如下:
    local iTest
    iTest=0
    public iSqlcon
    iSqlcon=Sqlcon(Dsn,DsnUser,DsnPws)  && Dsn为DNS,Dsnuser为用户名,DsnPws为密码
    sqlexec(iSqlcon,"Select field_a as a,field_b as b "+;
                      "from test_tab "+;
                     "where field_a = ?iTest and field_b = ?iTest",'test_tmp') 
    (注:这里变量、字段、表的名字我是代表意思的,要换成你实际使用的)
    如上,变量前加'?'就可以使用,这样写代码要方便清楚多了,象那样转成字符串再连接的,看的不清,容易出错!对于?后只能是变量,不可以是运算式!
    还有关于这个SQL字符传长度会大于255的问题:当整句长度过长时,中间如例用"+;"将字符串分割连接起来就可以了,只要每行不过长就没问题(过长会系统回有提示!),全句可以随意多长!
    希望有点帮助!
      

  27.   

    TO:yongyao(Archer_S.M.D)谢谢你的一点帮助....(好象不是一点呀!!!!!!!!)