VFP 学习、开发漫谈 (28)- 顺序查询
在 VFP 中,记录查询大体上可分为顺序查询和索引查询。这一节课,跟大伙聊一聊顺序查询技术。所谓顺序查询,是指按照实体表的记录号从头到尾进行查找。如果记录很少,比如:只有几条或几十条记录,则顺序查询可能比索引查询更快。
实现顺序查询的方法大致有以下几种:
一、LOCATE FOR/CONTINUE
先使用 Locate For 查找满足条件的首记录,然后再使用 Continue 遍历其他记录。
注意:Continue 与执行 Locate For 命令时所在的工作区是相关联的,在执行 Locate For 时,系统会自动将搜索条件作为该分区的一个内部属性来保存。当执行 Continue 时,系统会根据该分区保存的搜索条件向下搜索。下面的实例可以证明这一点:
程序代码:
SELECT 工资表 LOCATE FOR 实发工资>5000 && 在工资表中查找“实发工资>5000”的第一条记录 SELECT 员工表 LOCATE FOR 政治面貌="党员" && 在员工表中查找“政治面貌="党员"”的第一条记录 SELECT 工资表 CONTINUE && 在工资表中查找“实发工资>5000”的下一条记录 SELECT 员工表 CONTINUE && 在员工表中查找“政治面貌="党员"”的下一条记录
二、SET FILTER TO/SKIP
顺序查找的第二种方法:先使用 Set Filter To 设定一个过滤条件,然后再使用 SKIP 遍历其他记录。
程序代码:
USE 工资表 SET FILTER TO 实发工资>5000 GO TOP DO WHILE NOT EOF() ... SKIP ENDDO
注意:在执行 SET FILTER TO 命令后,系统并不会自动将指针移动到满足条件的第一记录,因此,在 SET FILTER TO 命令后,通常要执行 GO TOP。
三、SCAN FOR
在 SCAN 命令的 FOR 条件中指定过滤条件,从而遍历所有满足条件的记录。
比如,下列代码将显示所有财务人员的基本工资和奖金:
SELECT 工资表 SCAN FOR 部门='财务部' ? 姓名,基本工资,奖金 ENDSCAN
四、SELECT SQL
严格来说,SELECT SQL有其独特的搜索机制,将其归为顺序查询可能并不严谨。
根据我的经验,一般来说,SELECT SQL 要比索引查询慢,但要比 LOCATE FOR/SET FILTER TO/SCAN FOR 快。在顺序查找的几种方法中,我更喜欢使用 SELECT SQL一次性将满足条件的记录筛选出来,再加工处理。
下面举一个使用 LOCATE FOR/CONTINUE 连续搜索的实例。
源代码下载:
search.rar
(3.37 KB)
功能描述:
1. 在搜索框中输入姓名,回车或单击“搜索”按钮,则显示该学生的第一门课的考试成绩。
2. 再次单击“搜索”按钮,则显示该学生的下一门课的考试成绩。
3. 当显示到最后一门课的成绩,再单击“搜索”时,系统提示“未找到 XXX 的其他考试记录!”。再次单击“搜索”时,将重新从头搜索。
4. 当按下 Ctrl 键单击“搜索”按钮时,则始终是搜索满足条件的首记录(Locate For)。
5. 当修改条件后单击“搜索”按钮,则重新搜索首记录。
综上所述,系统仅使用了一个按钮就实现了“搜索首记录”和“搜索下一记录”的双重功能。如果设置了新条件或按下Ctrl键,则单击“搜索”按钮时搜索首记录,否则搜索下一条记录。
主要代码如下:
1. 在表单的 Init 事件中,新建表单属性 cSearch,用于保存搜索条件:
THIS.AddProperty('cSearch','')
2. 搜索按钮 cmdSearch.Click 代码如下:
程序代码:
LOCAL cValue,nRec cValue = ALLT(THISFORM.txtSearch.Value) && 要搜索的学生姓名 IF EMPTY(cValue) && 检测是否输入搜索值 MESSAGEBOX('请输入学生姓名!',48,'提示') THISFORM.txtSearch.SetFocus RETURN ENDIF nRec = IIF(EOF(),0,RECNO()) && 保存记录指针,用于查找不到记录时返回原记录 IF cValue == THISFORM.cSearch && 搜索条件未更改,查找满足条件的下一记录 CONTINUE IF !FOUND() IF nRec # 0 GO nRec ENDIF MESSAGEBOX('未找到“'+cValue+'”的其他考试记录!',48,'提示') THISFORM.cSearch = '' ENDIF ELSE LOCATE FOR 姓名 = cValue && 搜索条件已更改,搜索满足条件的首记录 THISFORM.cSearch = cValue && 保存搜索条件 IF !FOUND() IF nRec # 0 GO nRec ENDIF MESSAGEBOX('未找到“'+cValue+'”的考试记录!',48,'提示') THISFORM.cSearch = '' ENDIF ENDIF THISFORM.Refresh && 显示记录
3. 搜索按钮 cmdSearch.MouseDown 代码如下,以便实现按下Ctrl键时从头搜索:
* 当按下鼠标左键和Ctrl键时,清除保存的搜索条件,以便执行后续的 Click 事件代码时,搜索首记录 IF nButton = 1 AND nShift = 2 THISFORM.cSearch = '' ENDIF
注意:一次鼠标单击,会顺序触发 MouseDown、Click 和 MouseUp 三个事件,但在 Click 事件中无法判断是否按下了 Ctrl 键,只能在 MouseDown 或 MouseUp 中检测,但由于 MouseUp 在 Click 之后才触发,因此,本例中只能将代码输入在 MouseDown事件中。
4. 文本框 txtSearch.Keypress 代码如下,用于按下回车键时开始搜索:
IF nKeyCode = 13 && 按下回车键 NODEFAULT && 取消默认按钮引发的操作 THISFORM.cmdSearch.Click && 执行搜索 ENDIF
最后再声明一点:在顺序查找时,建议通过 Set Order To 将索引关闭,这种情况下,索引不但不能加快查找速度,可能还起到反作用。
[ 本帖最后由 liuxingang28 于 2014-9-15 11:05 编辑 ]