datawindow插入行问题
1,是不是如果数据源的表没有主键的话不能插入?
2,当一个从表与一个主表联系起来,主表的字段只为了显示,但不知为什么用insertrow(0)时,新增了一行,但每一字段内容不能输入
以上不知有没有说明白,请教各位,谢谢!
问题点数:100、回复次数:9Top
1 楼zyzj216(秋水玲珑寒)回复于 2003-06-04 16:57:08 得分 0
1)不是的,表没有主键也可以用insert插入数据
2)不明白Top
2 楼huangxinru(键盘手)回复于 2003-06-04 17:02:03 得分 10
置tab order不为0Top
3 楼boyliulang(liulang)回复于 2003-06-04 17:03:58 得分 50
1、不管能不能插入,表没有主建就是设计错误
2、检查你数据窗口每列的tab值,若tab值为0 则每列就不能得到焦点,当然也就不能输入。同时也要检查每列的readonly属性是否备选中,选中了就不能修改了
如果一个数据窗口牵涉到多表更新,会麻烦一些。你可以在www.baidu.com或www.google.com上搜索一下这方面得文章,在这就不多说了。 给你一片关于并发得文章,这是关于数据窗口得文章,对你有帮助:
并发控制
并发能力是指多用户在同一时间对相同数据同时访问的能力。一般的关系型数据库都具有并发控制的能力,但是这种并发功能也会对数据的一致性带来危险。试想若有两个用户都试图访问某个银行用户的记录并同时要求修改该用户的存款余额时,情况将会怎样呢?我们可以对PowerBuilder中的DataWindow进行设置来进行并发控制。所谓并发控制就是指在用户数据修改的过程中保证该数据不被覆盖或改变的方式,在下面的例子中我们将看到如何设置DataWindow来控制开发访问。为了说明问题,我们举这样一个简单的银行系统中的例子,某用户的存款状况如右:
我们假设事情的经过是这样的:公司的某员工在银行前台取款2,000元,银行出纳查询用户的存款信息显示银行存款余额20,000元;正在这时,另一银行帐户转帐支票支付该帐户5,000元,机器查询也得到当前用户存款20,000元,这时银行的出纳员看到用户存款超过了取款额,就支付了客户2,000元并将用户存款改为18,000元,然后银行的另一名操作员根据支票,将汇入的5,000元加上,把用户的余额改为25,000元,那么数据库管理系统是否可以接受这些修改呢?
在DataWindows的设计中,我们选择菜单Rows|Update…,会出现Specify Update Characteristics的设置窗口,在这个窗口中我们设置Update语句中Where子句的生成,以此来进行开发控制。在这里有三个选项,我们分别看一看在本例中这三个选项的结果:
(1)Key Columns:生成的Where子句中只比较表中的主键列的值与最初查询时是否相同来确定要修改的记录。在上述的例子中,转帐支票的操作将覆盖出纳员作出的修改,这样银行损失两千元。
(2)Key and Updateable Columns:生成的Where子句比较表中主键列和可修改列的值与最初查询时否是相同。在上例中两次查询出的结果都是有两万余额,当第一个人修改余额时,余额仍是二万元,所以修改成立,而支票转帐操作时余额已不是二万,所以该列不匹配,修改失败。
(3)Key and Modified Columns:Where子句比较主键和将要修改的列,在本例中,结果与Key and Updateable Columns的选择相同,因为余额已改变,不再与最初的查询相同,因此仍然不能修改。
让我们作另外一个假设,我们把银行后台作支票转帐操作改为冻结用户存款,即把状态字段的值改为冻结,而且事件发生的次序如下表,那么表中的次序4…前台出纳的修改能不能成立呢:
1.Key Columns:Where子句只比较主键值,显然出纳员的修改是允许的。
2.Key and Updateable Columns:生成的Where子句包括比较所有可修改的列,因此出纳修改时Statue字段为冻结与出纳查询时的tive不符,修改失败,同时显示错误信息。
3.Key and Modified Columns:Where子句的比较包括主键和要修改的列,由于本列中修改列仍为20,000元没有变化,所以出纳的修改可以成立。
在本例中,我们可以看到Key and Updateable Columns的选项最严格,可以避免出现状态列发生改变时余额作修改的错误,但是这也会禁止我们作一些本当允许的并发修改,如出纳修改存款余额,而业务员修改用户的联系地址等。因此我们应当根据实际情况,选择适当的Update设置。
根据我们使用数据库的不同,我们还有一些其他的控制并发访问和修改的选择方案,如对数据加锁。锁是一个用户避免其他用户对指定行作修改的操作。在结束一个事务如执行commit,rollback,disconnect等语句时自动将锁释放。如果您使用的DBMS支持锁的操作,在Power-Builder的DataWindow设计时,Select语句可在from子句中加上with holdlock:即在data Window的SQL Window中,在表窗口的标题处点击右鼠标,弹出菜单的最后一个选项即为Holdlock。选择该项,生成的SQL语句将在re-trievel()函数执行后将所查询的数据加锁,以避免其他用户的修改访问,直至commit,rollback等事件发生后解锁。这种方式带来的问题是,当用户查询完数据后可能离开计算机长时间不用,这段时间内其他用户均无法修改数据。此外有些DBMS如Sybase等不支持行级锁,也就是说当你对某一行查询时更多的行都被上了锁,这就更增加了并发处理的局限性。另一个值得注意的问题是在多窗口应用中某一个窗口的事务提交将会导致使用一事务中其他数据窗口的查询行解锁,这时修改将可能发生错误。某些DBMS系统支持一个称作"时间戳(timestamp)"的数据项来控制并发性。每张表中都有一个时间戳的数据列,当Insert语句或Update语句对数据行作修改时该列自动被修改为当前时间。当你要作修改时,where子句可检查时间戳列在查询时和修改时两个值是否相符,以此来确保您作出的修改不会覆盖别人的修改,因此这种确认方式与key and Updateable Columns选项相同。即使两个用户对同一行的不同列作修改,后一个修改者也将失败。在常用的关系型数据库中Sybase和Microsoft的SQL Server支持时间戳的使用。而在PowerBuilder中,不管用户后台连接何种数据库,只要表中带有timestamp的列名且数据类型为datetime,PB将自动忽略Update characteristics的选项,而在where子句中生成主键和时间戳列的比较。
如果您所用的数据库不支持时间戳但支持触发器,您也可以在表中增加一列整数型的列。当有对表中某种记录作修改时,该列自动加1。下列使用的是Watcom数据库,对Shipper表增加Updcnt字段并作两个触发器,这样任何用户或进程试图修改某行记录时,该字段均可发生变化。
对INSERT触发器的编写如下:
DROP TRIGGER INS—SHIPPER’
CREATE TRIGGER SHIPPER BEFORE INSERT ON SHIPPER
REFERENCING NEW AS Newvalue
FOR EACH ROW
BEGIN
SET newvalue.UpdCnt=newvalue.UpdCnt+1;
END'
同理可编写UPDATE触发器。
在您的PowerBuilder应用之中,除表的主键外,必须再加上这一列作为检测列加入Update语句中的Where子句中,这样再作Update操作时,后台数据库会比较修改时与用户作Retrieve操作时数据是否相等,以确认是否能作修改。在DataWindows中在Specify Update Characteris-tics的对话框的右下角的Unique key column(s)中加上Updcnt一项,同时注意where clause中选择Key columns,这样PowerBuilder在构造where子句时就会认为Updcnt亦是表的主键,而成为检测项。
当数据窗口的Update函数被调用后,触发器将修改过记录中的Updcnt列表为新值,为保证下一次修改能够有效,您应当立即作Retrieve()以使DataWindow缓冲区中Updcnt的值与数据库相同。显然修改后立即查询的代价要比其他任何一种并
发控制的代价要小得多。Top
4 楼coolingpipe(冷箫轻笛)回复于 2003-06-04 17:11:45 得分 10
2,当一个从表与一个主表联系起来,主表的字段只为了显示,但不知为什么用insertrow(0)时,新增了一行,但每一字段内容不能输入
设置一下数据窗口的UPDATE属性
还有tab order!Top
5 楼boyliulang(liulang)回复于 2003-06-04 17:11:52 得分 0
给你篇多表更新得文章.
用DataWindow实现对多表的修改
在开发中,我们有时会遇到用一个DataWindow来表现数据库中多个表中数据的情形,这时DataWindow用到的SQL Select语句是一个多张表连接的视图。当我们对这样一个DataWindow中的数据进行修改并提交数据库时,我们将会发现我们并不能简单地使用一条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语句只是在要修改的表名中使用DATABASE.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子句,由于系统自动地将多个表中所有的列都加到SET子句和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语句,PowerBuilder将自动构造成这样的一条语句:
上述三条SQL语句在提交数据库时都将产生"Invalid column name ‘id' "的错误,很明显,"id"这一个字段并不在custumer这一张表中。此外SALES-ORDER这张表的内容并没有进行修改。
为真正实现对多表数据的修改,我们可以编写这样一个函数f-MUpdate()。
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,ls-err,ls-updatekeyll,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包含列的数量
ls-err=a-dw.object.DataWindow.Column.Count
ll-maxcol=Integer(Is-err)
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+as-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语句是:Top
6 楼Changefish(小翼【嘘。。。别出声!我是从80端口进来的】)回复于 2003-06-04 17:14:24 得分 10
1.是否没有建主键,没有主键缺省是不能更新的,要去update属性那儿改
2.是否是多表联合的数据窗口(其缺省为不可更新)
3.是否数据窗口用的是external数据源,该方式是无法更新的
4.tab order是否为0
还有不明白的话,用“update‘搜索一下,很多贴Top
7 楼SilverSands(洞庭浪子)回复于 2003-06-04 17:15:30 得分 10
1)表没有主键也可以用insert插入数据
2)主键表作为下拉数据窗口只用做显示就可以了。
Top
8 楼nbnasom(阿飞)回复于 2003-06-04 17:59:16 得分 10
表没有主键也可以用insert
修改UPDATE属性与TAB属性Top
9 楼livi(rr)回复于 2003-06-04 23:30:11 得分 0
谢谢各位!Top




