首页 新闻 论坛 群组 Blog 文档 下载 读书 Tag 网摘 搜索 .NET Java 游戏 视频 人才 外包 培训 数据库 书店 程序员
中国软件网
欢迎您:游客 | 登录 注册 帮助
  • 关于数据窗口更新数据表的问题
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-05-24 18:32:59 楼主
    用UPDATE函数怎么更新不了?dw_1.update()
    20  修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-05-24 18:44:221楼 得分:0
    看看这个我想可能有用从网上找的:
    PB中 autocommit 和 commitondisconnect 两个连接参数的应用[收藏]2007年07月15日 星期日 16:48        想必大致了解PB的朋友都知道 transaction 的 autocommit 属性,但是我知道很多朋友对这个属性了解得并不很透彻,在今天晚上之前,我也如此,刚才仔细查了一下关于这些属性的东西,明白了一些,现在写下来,权当现炒现卖了,呵呵。

            AutoCommit

            the automatic commit indicator (SQL Server only).

          pb帮助中简单的这样描述这个属性,自动提交的指示器,只针对 SQL SERVER 数据库。

          但有时候我们看到了令人十分费解的的现象。当我们将全局的trsaction 的 autocommit 置为 false 我们在数据窗口的保存脚本中,仅仅简单的写上一句 dw_1.update(),并不进行commit; ,数据窗口是能够进行更新的。

          这看起来视乎非常不可思议,这样的话,autocommit 有何意义呢?commit 又有何意义呢?

          大家忽略了一个另外的参数commitondisconnect 这只是 数据库的一个连接参数,并不是transaction 的一个属性。他的含义是:如果该值为“yes”,那么不管autocommit 是true还是false,在disconnect之前,如果还没有没有提交的DML,transaction将会自动的提交一次。

          这样我们上面碰到的问题就不能解释了。注意这个参数的默认值是YES,也就是说如果你不主动的这样设置的话  SQLCA.DBParm = "CommitOnDisconnect='No'"  ,你所做的修改将会保存进数据库。这个看似实用的功能却经常会给我们带来麻烦,导致数据的不一致性。

          例如 当一个较长的事务执行了前面几步尚未Commit时发生数据库连接断开(非法操作、强行退出、死机等)此时会发生已执行的SQL不能回滚,但在退出前transaction 会自做多情地 将已经执行但还没来得及提交的DML 提交,从而导致数据错误(如库存已加但入库单却未打上入库标志)  为防止此类错误发生应设置为:数据库连接断开前不自动提交,即CommitOnDisconnect='No'

        再回到最开始提出的那个问题,如果我们将CommitOnDisconnect置为 yes,而 autoCommit 置为 false的话,将会发生更加严重的后果,就是 如果我们在 程序中 有 DML 或者 数据窗口的update()时如果,我们忘了手动的Commit的话,被操做的那个或那些表将会被锁住,其余的人不能访问,或者已经将表的数据读到本地,但不能保存,直到第一个人访问该表的那个Transaction 断开连接。

          上面说的是忘了写commit的情况,实际上即使你写了,commit ,如果commit和DML或者update()如果相隔太远的话,也会在执行DML或者update()  和 执行 commit 之间的时间内被锁住

        可以试着做这样一个实例来验证:

          假设有表t_test ,仅一个字段 test  numeric 10

        做一个数据窗口对象 d_test,其SQL语句为 select test from t_test

        做一个窗口 w_test,有如下控件 dw_1 ,cb_new,cb_save,cb_commit,cb_disconnect,cb_exit

          窗口open事件为  dw_1.dataobject = 'd_test'

                                    dw_1.settransobject(sqlca)

                                      dw_1.retrieve()

          按钮的click 事件分别为 cb_new :dw_1.scrolltorow(dw_1.insertrow(0))

                                                cb_save:dw_1.update()

                                              cb_commit:commit;

                                              cb_disconnect:disconnect;

                                              cb_exit:close(parent)

          当然 Application 的open事件里要将autocommit 设为 FALSE 将commitondisconnect 设为 yes

    典型代码为为

    SQLCA.DBMS = "MSS Microsoft SQL Server 6.x"
    SQLCA.Database = "qhet"
    SQLCA.ServerName = "."
    SQLCA.LogId = "sa"
    SQLCA.AutoCommit = false
    SQLCA.DBParm = "CommitOnDisconnect='yes'"
    connect using sqlca;

    open(w_test)

    运行后点new 按钮,填上符合的数据后,点 save ,然后,在PB的数据库画板中执行任何关于表t_test的sql语句均无法执行,如select * from t_test,将会一直处于等待中,直到你点按钮 commit 或者 disconnect 中的任何一个,sql语句才能得以执行。

    上面这个小例子模拟了以上所说的过程。

    以前我曾遇到过遇到过这些问题,当时不知道什么原因,现在总算恍然大悟了。

    那么我们该怎么解决这个问题了.

    可以这样,我们将autocommit 设为true,将commitondisconnect 设为 no,

    autocommit 设为true 有如下好处,1.如果我们的更新很简单,比如仅仅涉及对一个表,那么我们可以仅仅写一条 upate()就行了,将commit 或rollback的工作交给tansaction 来完成,考虑oracle和其他数据库,最好不要这样做,但如果确定是针对 SQLserver的,这样做师妹有问题的。

                                                          2.杜绝了上面说的长时间等待的情况,即使我们忘了写commit,程序会自动commit,其他用户不用等待。

    但这样做又有一个隐患,即如果要对多个表进行更新,我么不能简单的将commit和rollback 托付给transaction,如果我们这样做将会使数据不完整,也就是说transaction将会自动 一个表一个表的commit或者rollback,这样就会出现如 订单数据保存进数据库,但订单明细没有保存进数据库 的问题

    我们可以这样来处理一下

    做以下三个全局函数

    //************************************

    gf_begin_transaction

    //参数ao_environment 类型 transaction

    //返回值类型 boolean

    ao_Environment.AutoCommit = False
    if ao_Environment.SQLCode <>0 then return False
    return True

      //***********************************************

    //**********************************************

    gf_commit_transaction//参数返回值同前一个

    Commit Using ao_Environment;
    if ao_Environment.SQLCode <>0 then return False
    ao_Environment.AutoCommit = True
    if ao_Environment.SQLCode <>0 then return False
    return True

    //************************************************

    //************************************************

    gf_rollback_transaction//参数返回值同前一个

    Rollback Using ao_Environment;
    if ao_Environment.SQLCode <>0 then return False
    ao_Environment.AutoCommit = True
    if ao_Environment.SQLCode <>0 then return False
    return True

    //********************************************


    这样我们一旦又多个表更新的情况可以使用l类似这样的结构来处理

    gf_begin_transaction(SQLCA)

    dw_1.update()

    dw_2.update()

    delete from table_1......

    insert into table_2 ......

    ...................

    ...............

    if sqlca.sqlcode = 0 then

    gf_commit_transaction(sqlca)

    retrun

    else

    gf_rollback_transaction(sqlca)

    //error handle code here

    end if


    考虑到autocommit对除了sqlserver以外的其他数据库不起作用,我们可以在每一个需要更新的地方都已这三个函数来包围。

    这样就可以万无一失了。

    说明:1.autocommit 仅对sqlserver 起作用,而commitondisconnect 对大多数数据库都起作用,可以查看相应DBMS的手册

              2.autocommit 仅在 PB 脚本中起作用,而在数据库画板中是不起作用的,不如即使你在database profile 中将 autocommit 设为false,在数据库画板中执行的DML语句也会马上被commit掉

    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • jlwei888
    • 等级:
    发表于:2008-05-24 19:03:392楼 得分:0
    说得很全了,具体要看提示!
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-05-24 19:10:433楼 得分:0
    打开数据窗口画板 ->ROWS->UPDATE PROPERTIES....选几个勾就可以了
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • lian_yi
    • 等级:
    发表于:2008-05-24 19:16:154楼 得分:0
    唉。。
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-05-24 22:09:375楼 得分:0
    mark~~
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-05-25 13:48:366楼 得分:0
    这位大哥,请教一下在数据窗口画板里勾哪几个属性呢?谢谢!
    我的数据库是在POWERBUILDER里建的,不是SQL SEVER的
    修改 删除 举报 引用 回复

    网站简介广告服务网站地图帮助联系方式诚聘英才English 问题报告
    北京创新乐知广告有限公司 版权所有 京 ICP 证 070598 号
    世纪乐知(北京)网络技术有限公司 提供技术支持
    Copyright © 2000-2008, CSDN.NET, All Rights Reserved