荔园在线

荔园之美,在春之萌芽,在夏之绽放,在秋之收获,在冬之沉淀

[回到开始] [上一篇][下一篇]


发信人: Peter (小飞侠), 信区: Program
标  题: 用DataWindow实现对多表的修改
发信站: BBS 荔园晨风站 (Wed Jan 27 17:51:24 1999), 转信


   在开发中,我们有时会遇到用一个DataWindow来表现数据库中多个
表中数据的情形,这时DataWindow用到的SQL Select语句是一个多张
表连接的视图。当我们对这样一个DataWindo w中的数据进行修改并
提交数据库时,我们将会发现我们并不能简单地使用一条dw.update()
来实现同时对数据库中多张表的修改。
    事实上,系统在DataWindow中提交数据库并生成UPDATE语句时所
根据的仍然是图一这个窗口。在以前的章节中我们曾介绍过利用这个
窗口中一些不同的选项实现数据库的并发控制,这里我们再讲一下这
个窗口中的选项对生成UPDATE语句的其它影响。
    当我们调用UPDATE函数时,这个窗口中有四个域将被涉及:
    ·Where Clause for Update/Delete where子句的生成依据。这
个选项主要是用来进行并发控制的,这里不再赘述。
    ·Updateable Columns可修改的列。这是一个我们将遇到麻烦的
地方。PowerBuilder只能同时对一张要修改的表进行管理,所以我们
不能一下子指出所有表中所有要修改的列。在这里我们只能指出某一
张表中要修改的列,以后在程序中用Modify语句依次指定其它每一张
表中要修改的列。
    ·Table to Update将要修改的表。PowerBuilder只支持一张表
的修改,所以我们也只能在这里只指定其中的某一张表,其余的表也将
要利用Modify语句修改。
    ·Unique Key Columns唯一键的列。这也是我们要注意的地方,
因为PowerBuilder生成的UPDATE语句只是在要修改的表名中使用DATA
BASE.OWNER.TABLE这样的全称,而引用某列时只是简单指出列名,而不
用DATABASE.OWNER.TABLE.COLUMN这样的全称。所以,如果我们这里用
到的唯一列标识不属于上面"Table to Update"中定义的表的列,这一
条SQL语句将出现语法错误。
    PowerBuilder在DataWindow中产生的UPDATE语句和DELETE语句如
下:
    ●UPDATE database.owner.table
    SET column=somevalue,
    WHERE UniqueKeyColumn=somevalue;
    ●DELETE FROM database.owner.table
    WHERE UniqueKeyColumn=somevalue;
    在一条SQL UPDATE和DELETE语句中,所有引用的列名均不使用列
的全称,因此对列名的确定完全由update table来决定,在UPDATE语句
中所有修改属性均设为TRUE,而且用户进行过修改的列都将加到SET子
句中。PowerBuilder根据用户对"Where Clause for Update/Delete"
的选择形成WHERE子句,由于系统自动地将多个表中所有的列都加到S
ET子句和WHERE子句中, 而PowerBuilder又是根据用户指定的update
table来确定列,因此我们显然是无法得到一个准确的SQL语句的。我
们来看这样一个实例(本表可以在PowerBuilder DEOM数据库中得到,
注意:如果我们希望某一列不被修改,我们可以在DataWindow画笔中将
TABorder设置为0): 图一
    CUSTOMER.Customer-ID=101
    CUSTOMER.FirstName=Michaels
    CUSTOMER.LastName=Devlin
    CUSTOMER.Address=3114 Pioneer Avenue
    SALES-ORDER.ID=2001
    SALES-ORDER.order-date=09/14/94
    我们将其改为:
    CUSTOMER.Address=1905 Maple Avenue
    SALES-ORDER.order-date=12/11/94
    如果我们只是用dw.update()语句来形成UPDATE语句,PowerBuild
er将自动构造成这样的一条语句:
表1
    上述三条SQL语句在提交数据库时都将产生"Invalid column nam
e ‘id' "的错误,很明显,"id"这一个字段并不在custumer这一张表
中。此外SALES-ORDER这张表的内容并没有进行修改。
    为真正实现对多表数据的修改,我们可以编写这样一个函数f-MUp
date()。
    integer f-MUpdate(a-dw,as-update-table)
    a-dw-DataWindow名称;as-update-table-将要修改的表名的全称

    Long ll-ipos,ll-maxcol,i
    String ls-colnam,ls-mod,ls-table-name,lserr,ls-updatekey
ll,ls-qualifier="
    //从传递的参数中分离出表名和域名
    ll-ipos=Pos(as-update-table,"·",l)
    If(ll-ipos>0)Then
    ls-qualifier =Left(as-update-table,ll-ipos)
    as-update-table=Mid(as-update-table,& ll-ipos+1)
    ll-ipos=Pos(as-update-table,"·",l)
    If(ll-ipos>0)Then
    ls-qualifier=ls-qualifier+&
    Left(as-update-table,ll-ipos)
    as-update-table=Mid(as-update-table,& ll-ipos+1)
    end If
    End If
    // 得到这个DataWindow包含列的数量
    lserr=a-dw.object.DataWindow.Column.Count
    ll-maxcol=Integer(Iserr)
    If(ll-maxcol<1)Then
    Return 1
    End IF
    // 确认DataWindow中的每一列是否属于要修改的表中的列,如是
将其update 属性设为Yes,否则为No.
    FOR i=1 To ll-maxcol
    ls-mod="#"+String(i)+".Name"
    ls-colnam=a-dw.Descibe(ls-mod)
    ls-table-name=a-dw.Descibe(ls-colnam+&".dbName")
    ls-table-name=Left(ls-table-name,&)
    (Pos(ls-table-name,"·",l)-l))
    If(Upper(as-update-table)=Upper(ls-table-name))Then
    ls-mod=ls-colnam+".Update=Yes"
    Else
    // 如果该列不在可修改的表中,
    // 而其为主键的属性为TRUE
    // 将其列名存在ls-updatekey[ ]中
    // 并将其主键的属性设为FALSE。
    //由于PB不保留列的全名,我们不能。
    // 保留非修改表的键的名称。
    // 所以我们将其保留在数组之中,以便其恢复
    If(Upper(a-dw.Descibe(ls-colnam+".Key"))=" YES")Then
    ls-updatekey[UpperBound(ls-updatekey[ ])+1]=ls-colnam
    ls-mod=ls-colnam+".Key=No"
    If(a-dw.Modify(ls-mod)<>"")Then
    Return-2
    End If
    End If
    ls-mod=ls-colnam+".Update=No"
    End IF
    //  确认修改是否成功
    If(a-dw.Modify(ls-mod)<>"")Then
    Return-2
    End IF
    NEXT
    // 将修改表名设置为全称
    a-dw.object.Data Window.Table.UpdateTable=ls-qualifier+a
s-update-table
    // 修改DataWindow
    If(a-dw.Update(TRUE,FALSE)<>1)Then
    Return-5
    Else
    // 将DataWindow恢复为其原来的状态
    ll-maxcol=UpperBound(ls-updatekey)
    FOR i=l to ll-maxcol
    ls-mod=ls-updatekey[i]+".key=Yes"
    If(a-dw.Modify(ls-mod)<>"")Then
    Return-6
    End If
    Return 0
    End If
     调用这一函数时应遵守以下规则:
    ●保证数据的参照完整性,应当先修改父表后修改子表;
    ●在DataWindow画笔中为每张表建立唯一主键;
    ●在图一窗口中,将该DataWindow设为允许修改;
    ●指定所涉及的任意一张表为修改表,表中的任一列为可修改列
。以保证DataWindow有修改权,这样我们调用的函数就可以覆盖这一
设置。
    ●不要将并发控制选为key and modified columns,这个函数无
法在这一条件下工作。
    ●将表名的全称DATABASE.OWNER.TABLE传递给这个函数,特别是
在这个DataWindows是对多个数据库进行操作时。
    在上例中,我们可以这样调用这个函数
    f-MUpdate(dw-l," dbo.sales-order")
    f-MUpdate(dw-l," dbo.customer")
    最终我们得到的UPDATE语句是:

--
※ 来源:.BBS 荔园晨风站 bbs.szu.edu.cn.[FROM: 192.168.1.3]


[回到开始] [上一篇][下一篇]

荔园在线首页 友情链接:深圳大学 深大招生 荔园晨风BBS S-Term软件 网络书店