关键字:progress 数据库 4GL database
progress中的数据库是关系型的,具备关系型数据库的基本特征,当然没有像oracle那样复杂了,甚至说比sql server或者my sql都要简单。最简单的还是progress语言访问自己的数据库。
这里假定你已经有了自己的数据库(关于数据库的创建和维护,以后再讲),这里主要说怎么开发。
1.数据库的连接
连接数据库,有两种方式,一个是动态连接,一种是静态连接。
所谓的静态连接就是在程序启动的时候数据库作为一个参数直接连接,这个是由prowin32命令实现的,对应的在unix下是_progress命令。
prowin32的使用格式如下:
prowin32 -p main.p -param paramString -db dbname -T c:/temp -H dbserver -S 5000 -pf c:/myapp/db.pf -ininame c:/myapp/myapp.ini
-P参数,就是指定你的主程序,当然也可以是.w文件
-param 就是你要输入的参数。 我们知道,一般的程序或者命令需要参数,这个就是。在c/c++或者java里访问参数是在main函数中,那么progress怎么获取这个参数呢?
这就要说到一个系统句柄session,它有一个parameter属性,可以用这个来访问它。 比如iparameter = session:parameter.整个参数是一个双引号引起来的字符串,如果你又多个参数需要输入,你可以把这下参数合并为一个以某字符分割的字符串列。
-db 就是你要连接的数据库名字
-T 表示你要使用的临时目录
-H 是数据库所在的服务器名字或者IP
-S 端口
-pf就是parameter file,也就是说你可以把一些参数写在一个文件里.比如我想连接两个数据库db1,db2;可以写两个文本文件,内容分别是:
-db db1 -H dbserver -S 5000和-db db2 -H dbserver -S 5001然后分别存为db1.pf,db2.pf. 你就可以prowin32 -p main.p -df db1.pf -df db2.pf同时连接两个数据库了.
设置你还可以在.pf文件里面再次使用-pf参数
-ininame你要使用的ini文件,里面定义了你要使用的字体,颜色等等多对应的索引值.
那么动态连接,值得就是在程序文件里在进行连接,比如在main.p里边,可以使用connect语句:
connect db-name|value(db-name). 比如connect -db mydb1 -H dbserver -S 5000.或者connect value("-db mydb1 -H dbserver -S 5000"). 后边的用法通常是可以把你的数据库连接参数化,比如有两个定义一样的数据库但是在不同的服务器上.或者在同一服务器上但是数据库名字不一样,你可以使用-ld选项,ld就是逻辑名.
比如connect -db mydb1 -ld mydb2 -H dbserver -S 5001. 那么你就要使用mydb2前缀来引用mydb1数据库,相当于起了个别名.
注意一点的是,接下来访问数据库的语句不能和connect在同一个.p文件中,你必须把访问代码写在另外的.p文件中然后再调用之.
相应的connected(db-name)是一个用来判别数据库是否已经成功连接的函数.
disconnect则是用来断开数据库连接的.
disconnect db-name|value(db-name).
2.访问数据库中的表和字段
假设有这样的一个数据库,名字叫mydb,其中有一张表order:
field-name field type
order-num char
cust-num char
goods char
quantity decimal
order-related char
这里假定你的开发环境已经连接了数据库(在开发环境中连接数据库是一个简单的事情,你只要按照几个参数-db -H -S填充就行了),那么引用数据库是这样:
var1 = mydb.order.order-num. 如果只有一个数据库的话,mydb.可以省略。
当你访问数据库的时候,需要用到以下语句:
for each ... 和 find...
for each table-name where field1 = value1 and field1 = value2 ... no-lock:
your statement.
end.
for each 语句的常用方法很简单,就是一个循环。你的表名其实就是一个buffer--缓冲区。progress会把数据库中的纪录取回到当前的缓冲区中。
当你访问数据库的时候,有三中所可以使用,no-lock,share-lock和exclusive-lock,并且缺省的选项是share-lock.它们三个的区别如下:
no-lock:意味着其实progress没有对数据库施加任何限制,在你访问当前记录的时候,别人也可以访问并且修改。
exclusive-lock:排他性锁,使用这个选项,则意味着任何别的人都不能访问当前纪录,当然更不能修改了。这个主要是修改时使用的。
share-lock: 当你使用share-lock的时候,就意味着别人虽然也可以同时读取该记录的值,但是不能修改它。当你修改当前记录的时候,progress会自动施加exclusive-lock.
在你的for循环中,如果下一条记录被人锁定了会怎样呢?它会一直阻塞,直到这个纪录被解锁为止。
下面是一个例子:
for each order where order.order-num = "o00001" no-lock:
display order.
end.
这里的display语句会显示该记录的所有字段。
如果想把显示的结果排序怎么办呢,可以使用by选项。其用法是by field-name [descending]. 缺省会是ascending升序排列。 如果有多个列需要排序,你可以使用多个by 选项。
for each order no-lock by order-num by cust-num descending:
display order.
end.
下面说一说find语句。find的基本语法是:
find [ first | next | prev | last | current] table-name where {where clause} [no-lock|share-lock|exclusive-lock] no-wait no-error.
find语句会把匹配的纪录取回到当前的缓冲区中。
first是返回匹配的第一个记录
next,prev,last同样的道理。 具体取回那一条记录,是跟索引相关的。
current是把当前的纪录内容重新取回,当然你也可以在此更改你的锁选项。
如果没有记录匹配,则当前记录为空。如果要去的纪录被锁定,则find会被阻塞,没有纪录被返回。如果你不像这样的话,就可以使用no-wait选项,这样find会立即返回。
如果没有匹配纪录,progress会谈出一个错误警告.如果你不想有这个警告的话,就可以使用no-error选项.
那么我怎么才能知道有没有纪录被返回呢,这里需要用到available函数,其使用方法是 available buffer-name. 如果缓冲区内有记录,则返回真,不然返回假.
比如:
find first order where order.cust-num = "cu001" no-lock no-error.
if available order then
display order.
else
message "no order for cust-num:cu001".
如果是纪录被锁定怎么辨别呢,就要使用locked函数了,其使用为locked(buffer-name).比如上例:
find first order where order.cust-num = "cu001" no-lock no-wait no-error.
if available order then
message "order ok".
else if locked(order) then
message "order locked".
else
message "no order".
find语句中也可以不指定first/next/prev/last/current,而是直接find order where order-num = "O001" no-lock no-error. 如果符合条件的记录不止一个的话,会引发一个警告,并且没有纪录被返回,因为它不知道取哪一个.这种情况下怎么分辨没有记录还是有多条记录呢,这就要用到ambiguous函数,其用法为ambiguous buffer-name.
find order where cust-num = "c001" no-lock no-error.
if avail order then
message "order ok".
else if ambiguous order then
message "more than one order".
else
message "no order".
3.什么是buffer
buffer是一个缓冲区,同时也是一个数据类型.你可以定义一个buffer.
define [[new] shared] buffer buffer-name for table-name.
当你要在一个循环内部再次访问该表的时候就要用到buffer了.比如:
define buffer border for order.
for each order where order.order-num = "O001" no-lock:
find first border where border.order-related = order.order-num no-lock no-error.
if available border then
message "order ok".
end.
表的名字就是一个缺省的buffer.
4.query
另外一种可以用到的方法就是使用query对象.其实query主要是使用在browser控件中的,就是相当于一个表格控件了.
定义一个query:
define query query-name for table-name/buffer-name cache n scrolling.
在定义query的时候,需要预先定义好要是用到的缓冲.并且不能更改.如果需要一个动态查询的话,可以使用动态的query.
cache n表明这个查询可以缓存n条记录.
scrolling表明可以随机查询缓存中的纪录.不然的话只能使用向前或者向后的一一寻找.
打开一个查询:
open query for each buffer-name ....
后半部分for each开始基本上就是一个for each语句.
如果该查询是在一个browser中的话,则它可以立即返回结果到缓冲区. 不然的话,只能在使用get之后返回到缓冲区.
获取纪录:
get first|last|next|prev query-name. get的作用就是把纪录从数据库拷贝到buffer中.
重新定位:
reposition query-name to row n | forwards n|backwards n.
reposition只能对采用了scrolling选项的query进行操作.
在调用了get之后,要确认是否有记录存在,一个方法是使用availabel语句,另外一种方法就是使用query-off-end函数.
query-off-end("query-name"). 如果当前没有记录,则返回真.
关闭查询:
close query query-name.
在你关闭查询之后,还可以重新打开,同时使用新的查询字句.
define query mq for order cache 5 scrolling.
open query mq for each order no-lock.
get first mq.
repeat while not query-off-end("mq"):
disp order.
get next mq.
end.
if available order then
disp order.
else
MESSAGE "no order".
close query mq.
如果使用动态查询,以及表的连接该怎么办呢,下一次谈.
本文介绍了如何在Progress中连接和访问数据库,包括静态和动态连接方式,数据库表和字段的访问,以及for each和find语句的使用。还讨论了buffer的概念和query对象在浏览器控件中的应用。
9749

被折叠的 条评论
为什么被折叠?



