PowerBuilder DataWindow画板的更新特性详解

根据当前应用程序的需要和数据完整性的需要去改变DataWindow的更新选项。

要改变DataWindow对象执行更新操作的方式,可从Rows菜单下选择Update Properties,打开Specify Update Properties对话框。(如下图)

更新特性对话框

对话框分为5块内容:

1.指定允许更新选项及要更新的表

如果DataWindow中的数据不止是查询,需要更新的话,勾选Allow Updates,并在Table to Update下拉框指定要更新的一张表,下拉框的默认选项是数据源中的表或者视图。如果视图含多张表,必须指定视图中的一张表。

2.指定可以更新的列和键列

Updateable Columns框中选蓝要更新的列,如果在数据源中拥有多于一张的表,用户仅能更新其中一张表中的各列,尽管所有的列名都出现在列表框中。
Unique Key Column(s)框选择能唯一标识行的列(或复合列)。如果在数据源的SQL Selection List中已经指定了主键标,用户可以单击Primary Key按钮。

3.指定执行更新和删除SQL时的where子句(Where Clause for Update/Delete)

Where Clause for Update/Delete组合框包含了三个单选按钮,它们为维护数据的完整性提供了三种选项,并为数据库加锁提供了不同的选择。当某行被选择时,用户可以通过DataWindow对象来提供完整性保护而不是给某行或某页上锁(取决于数据库加锁机制)并防止其他用户检索该行。这三个选项为:Key Columns, Key and Updateable Columns和Key and Modified Columns。

3.1 Key Columns

指定了该选项,DataWindow将只使用在Unique Key Column(s)框中指定的键标列。此选项通常用于单用户应用程序中。当PowerBuilder生成Update或Delete语句时,它将比较某行检索的原始键标列值和当前数据库中此行的键标列值,如果两个值相等,更新和删除操作才会成功。

例如:假设Malcolm和Jonathan从顾客表检索到下列行,Customer_Id为主键,姓名,状态和地区为可更新列:
Customer_Id:110
Customer_Name: Simon Herbert
Status:Perferred
Region:Midwest

如果Jonathan将地区从Midwest改成Southeast,将使用键标列产生以下UPDATE语句:

UPDATE  customer
SET region = "Southeast"  
WHERE customer_id = 110  --Key Column; 

此UPDATE语句将成功地被执行。如果Malcolm也要改变此行(例如,将地区变为Northwest),也会成功执行,但会出现完整性问题。Jonathan的改变将被覆盖,因为键标列没被改动。因此,这个示例中,用户拥有高度并发性(两个用户都可访问和更改数据),但数据的完整性却非常差。

Malcolm改变此行时产生的UPDATE语句:

UPDATE  customer
SET region = "Northwest"  
WHERE customer_id = 110  --Key Column; 
3.2 Key and Updateable Columns

指定了该选项,PowerBuilder生成Update或Delete语句时,将比较原始键标列值、任何可更新列的原始检索值和当前数据库中这些列的值作比较。如果值都相等,更新和删除操作才会成功。这是推荐使用的方法,因为它提供了高度的数据完整性。

UPDATE customer
SET region = "Southeast"
WHERE customer_id = 110     --Key Column
AND name = "Simon Herbert"  --Updateable Column
AND status = "Perferred"    --Updateable Column
AND region = "Midwest"      --Updateable Column

Jonathan的更新操作将会成功。如果Malcolm又想改变地区,并试图进行更新,更新操作将会失败,因为WHERE子句没有改变,但是地区值现在是Southeast而不是Midwest。使用Key and Updateable Columns,尽管并发程度很低,但数据完整性却要高得多。

3.3 Key and Modified Columns

指定了该选项,PowerBuilder生成Update或Delete语句时,将比较原始键标列值、将要更改的可更新列的原始检索值和当前数据库中这些列的值作比较。如果值都相等,更新和删除操作将会发生。此方法是前两者的折衷形式。对于同一示例,如果两用户都想改变同一行的相同的列(例如region),第一个更新操作成功,第二个将失败,SQL语句将如下所述:

UPDATE customer
SET region = "Southeast"
WHERE customer_id = 110     --Key Column
AND region = "Midwest"      --Modified Column

如果前一个更新执行后,接着另一用户修改同一行记录的状态字段,由Preferred改为Exceptional,SQL语句如下所示:

UPDATE customer
SET status = "Exceptional"
WHERE customer_id = 110       --Key Column
AND status = "Preferred"      --Modified Column

这个更新操作将会成功,尽管数据已经改变了(region不同了)。因此在这种情况下数据完整程度低而并发程度高。此选项可用于两个用户同时修改相同的行时的情况,只要他们改变的是不同的列数据。

4 指定键列的修改方式(Key Modification)

指定的是如果用户改变了键标列值,更新操作将怎样发生。两个选项:Use Delete Then Insert和Use Update。

第一个选项是在删除了列以后,再用新的键值插入一个新的行。此选项减少了在数据库中重新组织的工作量,但它有着潜在的问题。如果主键是另一张表的外键并被指定为级联删除,用户可能就不想使用Use Delete Then Insert了。

警告:除了有触发级联删除的可能性之外,如果用户只检索表列中的一部分,update选项还是有用的。如果用户仅仅检索表20列中的5列并改变了主键值,使用Use Delete Then Insert选项会引起整行被删除,而且没有被检索的15个列中的数据将被丢失。

第二个选项将更新行中的键值。新的键值包含在更新过程中,和其他数据在一起,这就防止了外键和级联删除的问题。首选使用Use Update选项。

5 指定标识列(Identity Column)

此列表框用于为下拉列表中所指定的列(通常是键标列)生成序号。此选项仅仅用于支持序号生成的DBMS(也称为自增列)。通常不指定,选择None。

警告:如果用户指定了一个列为标识列,就不要将其选作为一个可更新列。如果确实想将该列选作可更新列,则对数据库执行的任何UPDATE都将失败。

补充实验:

新建一个DataWindow,指定第三点的Key and Updateable Columns,用户A和用户B同时更新同一行记录,用户A更新成功。而用户B接着提交更新时会收到报错Row changed between retrieve and update。无法更新。报错截图如下:

这里写图片描述

而指定为Key Columns,用户A、B都检索出同一条记录,则用户A更新成功,用户B更新也会成功且将A的修改覆盖了。如果用户B与用户A没有沟通的话,用户A就会感到莫名其妙,为什么我修改的信息被覆盖了。用户B也不曾知道该记录曾被A修改过。数据完整性体验极差。

当数据存在主次表时,当更新了次表数据后,主表数据在后台有变时。可利用刷新主表当前行的方法重显主表数据。 /************************************************************ 函数名称: f_refresh_currentrow(adw) 功 能: 刷新DW当前行数据,不可刷新NO update or 带arguments的DW 参数说明: adw 目标DW 返 回 值: integer 成功返回1,失败返回-1 作 者: sean 创建时间: 2010年8月18日 ************************************************************/ string ls_dataobject string ls_keys[] //key Column Name string ls_dbname[] //key field Name string ls_coltype[] //field style string ls_tablenm //table name string ls_condition //sql Condition long ll_currentrow //Current Row numeric long ll_column //Column count integer i datawindow ldw datastore ldatastore ldw=adw if ldw.rowcount( )=0 then return -1 elseif trim(ldw.describe( "datawindow.table.arguments"))<>'?' then messagebox('','刷新数据窗口当前行失败!,数据窗口需要参数',exclamation!) return -1 else ll_currentrow=ldw.getrow( ) FOR ll_column = 1 TO long(ldw.object.datawindow.column.count)//key names If ldw.Describe("#"+string(ll_column)+".key") ='yes' Then i++ ls_keys[i]=ldw.Describe("#"+string(ll_column)+".name") ls_dbname[i]=ldw.Describe("#"+string(ll_column)+".dbname") ls_coltype[i]=ldw.Describe("#"+string(ll_column)+".coltype") End If NEXT if upperbound(ls_keys[])=0 then messagebox('','刷新数据窗口当前行失败!,没有主键',exclamation!) return -1 else ls_tablenm=left(ls_dbname[1],pos(ls_dbname[1],'.') -1) //table name for i=1 to upperbound(ls_keys[]) if pos('numb,deci,long,',LeftA(ls_coltype[i],4) +',')>0 then ls_condition+="and "+ls_dbname[i]+"="+string(f_getitem(ldw,ll_currentrow,ls_keys[i])) else ls_condition+="and "+ls_dbname[i]+"='"+string(f_getitem(ldw,ll_currentrow,ls_keys[i]))+"'" end if next ls_condition=mid(ls_condition,4) //sql Condition ldatastore=create datastore ldatastore.dataobject=ldw.dataobject ldatastore.settransobject( sqlca) if f_addwhere_retrieve(ldatastore,ls_condition)=1 then if ldatastore.rowcount( )=1 then ldw.object.data[ll_currentrow]=ldatastore.object.data[1] ldw.setitemstatus( ll_currentrow, 0, primary!, NotModified!) //if ldw.getrow( )<>ll_currentrow then ldw.scrolltorow( ll_currentrow) end if else messagebox('','刷新数据窗口当前行失败!,条件语法错误',exclamation!) return -1 end if destroy ldatastore end if end if
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值