progress的数据库访问2

本文详细介绍了Progress 4GL中数据库的访问方法,包括如何通过FOR语句进行表之间的连接查询,表的自身连接,以及缓冲区BUFFER的使用。重点讲解了静态与动态BUFFER的区别,BUFFER-FIELD对象的属性以及BUFFER的方法。还提到了动态QUERY对象的创建和使用,以及外连接查询的实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

progress的数据库访问2

关键字: progress 4GL 数据库

1.数据库的连接

首先我们假设有这样两张表:
表 order:
field-name    field-type
oid         char
custid        char
ref-oid        char
quantity    decimal
unit        char

表 customer:
field-name    field-type
custid            char
custname    char
custaddr    char

这里custid在两张表里起一个联结作用。

假如有一个给定的订单号码mo1,想找出和它对应的客户信息:
for each(first) order where order.oid = mo1 no-lock,
    first(each) customer where customer.sutid = order.custid no-lock:
    display order.
    display customer.
end.

因为通常订单号是唯一的,所以for each和for first是一样的效果。同样一个订单只会对应一个客户。

如果反过来,已知客户号码名字cname,现在要找到该客户所有的订单:
for first(each) customer where customer.custname = cname no-lock,
    each order where order.custid = customer.custid no-lock:
    display customer.
    display order.
end.

这仍然是一个for语句,要注意,第二个字句直接使用each/first/last即可,不再需要多余的for. 并且如果你想的话,你可以连接两张以上的表。

这样的连接是一个自然连接。如果你要使用不等连接,只要改变一下操作符即可。

很显然,一个迪卡尔连接是这样的:
for each order no-lock,
    each customer no-lock:
    disp order.
    disp customer.
end.

当然对于这样的连接还有另外一种方法,就是使用嵌套的for语句:
for each order no-lock:
  for each customer no-lock:
      disp order.
      disp customer.
  end.
end.
当然了,这种方法会慢一些。

2.表的自身连接
在sql语句中是使用别名来定义自身连接的。在progress中同样如此,不过这里使用的是缓冲区buffer.
假定我们要对order这张表进行自身连接,oid=ref-oid:
define buffer border for order.
for each order where order.oid = o1 no-lock,
    each border where border.oid = order.ref-oid no-lock:
    disp order.
    disp border.
end.

3.再次介绍buffer
作为一个buffer,实际上有两种类型,一种是静态的,一种是动态的。
一个静态的buffer,前边已经使用过,现在重复一下作为对比:
define buffer buffer-name for table-name.
而一个动态的buffer,在变量上它是一个句柄:
define variable hbuffer as widget-handle no-undo.
create buffer hbuffer for table "table-name".

这里要注意的是,首先你要声明一个句柄变量,然后使用create语句来创建一个动态buffer.这个语法和define稍有不同。一个是前者有table关键字在表的前面,另外一个是表的名字必须是一个引在引号中的字符串变量。
因为是动态的么,所以表的名字也必须是可变的。
另外一点是,使用完之后需要释放内存:
delete widget hbuffer.
或者delete object hbuffer.

从一个静态的buffer可以获得它的句柄从而得到一个动态的buffer,就像c/c++语言里的取地址操作符&可以把一个变量转变为指针一样。
比如:
define variable horder as widget-handle no-undo.

horder = buffer order:handle.

对于一个动态的buffer对象而言,它不但有自己的属性,还有自己的方法可以调用。访问方法如下:
buffer-handle:attribute or buffer-handle:method

对于一个buffer对象,最最重要的还是怎么访问各个域,这就要谈到另外一个对象buffer-field.

4.buffer-field对象
buffer-field是一个特殊的对象,是因为没有对应的define buffer-field语句来创建一个对应的静态对象。得到一个buffer-field有两种方法:
define variable hbf as widget-handle no-undo.

1)从对应的buffer对象获得:
define variable hb as widget-handle no-undo.
hb = buffer order:handle.
hbf = hb:buffer-field("orderno"). 或者hbf = hb:buffer-field(1).
这种方法具有很大的灵活性,特别是结合buffer-field的属性。

2)直接获取句柄
hbf = orderno:handle in buffer order.

下面简单介绍几个buffer-field的重要的属性:
属性名            类型            说明
available           logical             表明该缓冲区是否有记录
buffer-handle       handle              获取该field所在的buffer句柄
buffer-name         character           获取该field所在buffer的名字
buffer-value[(i)]        具体的数据类型      该field所包含的值. 如果该field是一个数组的话,就可以使用索引i
can-read            logical        
can-write           logical
data-type           character           该field所包含的数据类型
dbname              character           所在数据库名       
extent              int                 返回维数
key                 logical             是否在某一索引中
name                character           field的名字。
position            int                 在buffer中的位置
string-value[(i)]        character          转化为字符串值
table               character           表名

下面是一些重要的buffer的属性以及方法
属性名            类型            说明
available               logical                 是否有记录
can-create        logical            
can-delete        logical
can-read        logical
can-write        logical
current-change        logical            是否有变化
dbname            character        数据库名
new            logical            该record是否是新创建
num-fields        int            
record-length        int             长度,单位byte
rowid            rowid
table            character        表名
table-handle        handle             
table-number        int            所在表在整个数据库中的序号

简单起见,这里的方法忽略了输入参数,具体可以查看帮助。至于返回类型,基本上都是logical,表明操作是否成功。
方法名            描述    
buffer-compare()        和另外一个buffer进行比较,看两者是否完全一样。结果即为返回值
buffer-copy()           拷贝另外一个buffer的值到该缓冲区
buffer-create()      创建一个新的纪录,并设置为缺省值
buffer-delete()    删除当前纪录 
buffer-release()    释放纪录
empty-temp-table()   清空临时表,该buffer句柄必须是一个临时表
find-by-rowid()    查找制定纪录并拷贝到当前buffer
find-current()          用来改变当前的锁定模式
find-first()      
find-last()
find-unique()

这里要说明的是,对于句柄的成员方法,都有对应的语句来操作静态buffer对象.这一规则同样也适用于query对象。

5.动态query对象

动态的query对象和buffer是类似的。
define variable qh as widegt-handle no-undo.
create query qh.

在使用动态query的时候,和静态的对象也差不多:
qh:set-buffers(buffer order:handle).
qh:query-prepare("for each order where order.oid = '" + string(你的oid) +"'").
qh:query-open.

set-buffers的参数就是buffer句柄,所以你也可以这样:
define variable ho as widget-handle no-undo.
create buffer ho for table "order".
qh:set-buffers(ho).
...

set-buffer最多可以添加18个buffer,因为你的查询语句可能是表连接语句。

首先获取第一个记录
qh:get-first.
使用qh:query-off-end属性来表明当前纪录是否是最后一个。

如果你要便利所有的结果,也可以这样:
repeat:
   qh:get-next.
   if qh:query-off-end then
      leave.  /*表明已经到了末尾,当前已经没有记录了,退出repeat循环*/
  else
   do:
      disp ho:buffer-field("oid"):buffer-value ho:buffer-field("custid"):buffer-value ho:buffer-field("refid"):value.
      /*注意这里对buffer句柄的引用,这全取决于你在set-buffers是所使用的名字,和具体的表的名字无关。*/
   /*当然你也可以这样*/
   define variable i as int no-undo.
      do i = 1 to ho:num-fields:
          display ho:buffer-field(i):buffer-value.
      end.
    end.
end.

对于query的常见属性以及方法,这里就不一一列出了。

6.外连接

外连接只能只用在query中,而不能使用在for语句中,并且只有左外连接。
define query qouter for order,customer.
open query qouter for each order no-lock,
    each customer [left] outer-join where customer.custid = order.custid no-lock.
对于上例,如果你想使用右外连接,那你只能改变两个表的先后顺序了。


   







 



 
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值