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.
对于上例,如果你想使用右外连接,那你只能改变两个表的先后顺序了。
关键字: 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.
对于上例,如果你想使用右外连接,那你只能改变两个表的先后顺序了。