日期:2012-06-23  浏览次数:20959 次

几乎每个完整的应用程序都会需要一个复合查询。建立一个功能强大的复合查询首先必须要能够动态

生成查询条件,其次应该能够对查询到的数据进行修改,最后这个复合查询最好能够对一对多的两个表建

立条件进行查询。

在VFP里建立查询的方法主要有这么几种:一是使用VFP中自带的SearchClass类;二是建立一个查询;

三是建立一个视图,其中包括参数化视图、宏替换Sql语句视图;四是建立一个Grid,将其数据源设置为

SQL语句或临时表。

不管哪一种方法,其实质都是使用SQL语句。

这几种方法各有各的优点,也都有缺点。

建立查询的方法最死板,只能建立固定条件的查询,并且不能更新数据,最不能满足要求。

SearchClass类功能强大,但是它只能对一个表建立条件进行查询,并且它的源代码太复杂了,几

乎难以进行修改定制;(初学者想必都有过用表单向导建立表单后试图修改txtbtn类、SearchClass类

的经历吧!看到源代码后有几个没昏倒?)

用将Grid的数据源设置为SQL语句或临时表的方法无法修改/更新数据,刷新数据也比较困难。(这

方面的问题在网易虚拟社区VFP版上有过许多讨论,大家可以去看看。)

建立视图的方法中,参数化视图也太简单。不管是用表单控件的值作参数还是用给参数两端加上引

号的方法都只能对固定的字段进行查询。如果是复合查询,难道要先建立几十个视图吗?

最有前途的办法还是用宏替换SQL语句建立视图的办法。视图有着能够对数据进行修改/更新的优点,

如果能够动态生成查询条件,那么就是最完美的查询了。

建立宏替换sql语句视图的具体办法是先动态生成一个Sql语句sqlstatement,然后用宏替换的方法使

用Create Sql view viewname as &sqlstatement来动态建立视图,最后将数据动态显示在一个Grid控

件中。

看到这里,VFP大虾们怕会大喊:Stop!你当我是菜鸟啊!你的办法从理论上虽然行的通,但实际做

起来就会碰到查询结果在表格上数据无法刷新的难题。俺早就试过不行了!你想骗稿费啊!

嘿嘿,这个难题偏偏给我解决了!这就是我洋洋得意的写这篇文章的原因!

问题的解决

==========

几个月前(好可怜^0^.....),我参照VFP的Sample中的Solution里的Interactively Bulid a sql

statement示例建立了一个复合查询,想将它集成到我自己的程序中。由于该示例是用browse窗口来显示

查询结果的,而我自己的应用程序使用了顶层表单,结果编译后运行才发现Browse窗口在顶层表单中无法

显示。于是我建立了一个有两个表单的表单集,用一个表单makesql动态生成sql语句,在另一个表单

form1上用grid来显示查询结果的数据,在给Grid设置数据源的时候,问题来了。首先使用临时表来作为表

格的数据源,结果第一次查询正确,更改条件进行第二次查询时碰到了众所周知的“不能更新临时表“的错

误;使用sql语句倒是可以,可是在表格显示数据前会莫名其妙的先出现一个Browse窗口,必须关闭它后

才会显示表格,由于browse窗口在使用顶层表单的程序中无法显示,结果导致程序无法继续执行,这个办

法也不行。

最后只能使用Create sql view viewname as &sqlstatement的办法了,先随便建立一个视图

tempview,把表格的Recordsourcetype属性设置为1-别名,Recordsource属性设置为视图别名tempview,

在表单makesql上建立sql语句后的代码中使用create sql view temp view as &sqlstatement建立视图

Tempview.

执行后发现,第一次查询正确,更改查询条件后再次查询,出现“视图已存在,要改写吗?“的情况,

按下“确定“后,出现的表格中没有数据。

避免出现对话框的问题好解决,在建立视图前先用rename view tempview to oldview,然后用

Delete view oldview将旧的视图删除就可以了。代码如下:

****************************************************************************

set database to databasename &&databasename是你的数据库名称

&&注意:即使你打开了数据库也必须写这个语句!否则会出现“找不到数据库“的错误。

if used(“tempview“)

rename view tempview to oldview

delete view oldview

endif

Create sql view tempview as &sqlstatement

=requery()

IF _TALLY = 0

#DEFINE MSG_LOC “没有找到符合条件的纪录!“

#DEFINE TITLE_LOC “没有找到纪录“

=MESSAGEBOX(MSG_LOC,64+0+0,TITLE_LOC)

ELSE

thisform.hide

thisformset.form1.show

Endif

*****************************************************************************

但是这样做了以后,表格上没有数据的问题仍然存在。查找资料后发现,用Create sql view语句编

程建立视图的方法,建立视图后要先保存视图定义,再打开视图后视图中才有数据。因此,必须将Creat

sql view语句部分代码修改如下:

************************************************

Create sql view tempview as &sqlstatement

use

use tempview

************************************************

满以为这下问题解决了,结果更惨。出现的表格上不但没有数据,连表头、网格都不见了!这个问题

百思不得其解,查找资料也没有结果,最后不了了之,一直困扰了我几个月。

就在昨晚,我上