|
单数据表查询部件指涉及一个数据表,包括与其相关的所有代码表的数据查找并将查询结果显示或打印的通用程序。有的查询结果要求输出到文件或网上,我们将之列入导出部件类,不在本文中讨论。涉及多数据表的查询也不在本文列入。
这类程序的核心代码是SQL语言的Select语句,该语句一般使用时如果不使用嵌套,一般由输出子句、数据源子句、条件子句、排序子句、分组及分组条件子句构成。在输出子句及条件、分组子句中要考虑聚集函数及其他计算式的要求。使用嵌套的目的有的是为了查询优化,另外,并、交、差、除问题的求解一般采用嵌套的Select语句设计,我们采用另外一组部件供调用,本文暂不论及。
在分析查询部件设计时,数据源将通过接口参数数据提供,代码可以要求先以某种方式通知程序提交使用,程序预先进行连接或全连接(设计二类部件,或提供接口参数进行选择确定)后按排序要求索引再供查询应用。
设计的主要内容是输出要求、条件子句、分组子句如何生成。
通常的输出是字段内容、关于字段聚集的内容,如果是其他表达式输出,范围太大,只能根据手中的资料提供少量资源。如果输出是字段内容,需要让用户给定是那些字段,可以通过接口参数带入,也可以提供所有字段名、各种聚集函数让用户选择给定。前者适用于专门的场合,用户操作较简单;后者使用灵活,有更好复用性,但界面显得比较复杂,对用户操作水平要求较高。输出界面主要
条件子句由字段名或与字段有关的计算式、大于等于等关系符、数据值三部分构成。例如,姓名=“张力”是一个条件式,由字段名:“姓名”、“=”、“张力”三部分构成。又分成单条件(一个条件式)、二条件(二个条件式经AND、OR、NOT联系成一个条件表达式)、多条件(多个条件式经AND、OR、NOT联系成一个条件表达式)等不同情况。
一、单条件最简单的是预先确定了字段名与关系符,在使用时用户提交数据值,再运行求满足该条件式的记录。所涉及的界面一般是一个标签,一个文本框,若干个功能按钮。例如,预先确定是根据姓名查询,要求用户给出具体被查的姓名,要求在数据表中查找该人的记录。设计方案:界面上给出: 姓名=? 再给出一个“开始查询”的按钮。问号处是一个文本框,用户将欲查找的人的姓名填写其中,再按“开始查询”,结果输出所查找的记录。
如果设计成可复用的程序,设计方案:在接口中给出字段名与关系符,在界面上设计一个标签,标签显示的内容为接口中给出的字段名与关系符的组合字符串,在标签后面添加一个文本框,留给用户输入欲查值。程序首先根据字段名查出该字段数据类型,将文本框初始化(整型定为0,字符型定为空等)。例如,接口中给定:姓名、等于
窗口中就形成如左图摸样(用多个□表示一个文本框): 姓名 = □□□□□
又例如,接口中给定:姓名、包含,
窗口中就形成如左图摸样: □□□□□ 包含在 姓名 之中。
用户操作时只需要填上要查找的数据就可以开始查询了。
如果要求能让用户在操作时可以从多个字段中选择一个进行查询,另外查询关系也不限定为等于一种,设计时可以将标签换为二个组合框,一个显示让用户选择的那些字段名,一个显示各种关系符,这样设计的部件用户操作起来麻烦一些,也要求用户对计算机操作更熟练,但是其优点不仅是可以满足用户任意单条件查询的需求,而且程序具有自适应性,用途更广阔。
实际设计的部件见清华大学出版社06年出版《Visual FoxPro程序设计》一书,作者:程学先、李振立、王莉、李军。参加该书工作的还有:曾玲、林姗、程传慧、杨晓艳、高霞、刘玲玲、熊晓青、黎柳柳、苏艳、蒋慧婷、陈莉、程传庆等。
以下是有关内容摘录。
*********************************************************************
最简单的单条件查询只需要在表单上放一个文本框,让用户输入欲查询的数据,再设计一个按钮,显示查询结果,就可以了。8.3节的图8.21是所设计的一例。以下介绍功能更加强的一个设计。
1、设计需求:(1)、能做等值查询,也能做其他单条件表达式的查询。(2)对查询的字段的历史数据提供列表框列表显示,使用户方便操作。(3)、提供模糊查询手段,随着用户输入查询内容,列表框中要显示最匹配的数据。(4)、结果输出除了列表显示外,提供常见的一些输出功能。(5)、设计成通用程序,查询字段名或字段的顺序号放在变量“字段号表”中,数据表名放在变量“数据表名称”中。
根据以上需求,设计界面如图11.27所示。
2、主要程序设计
1)、初始化程序代码
初始化程序的任务(1)、分析用户在变量“字段号表”中填的是所欲查的字段名还是字段号,如果是字段号,分析相应的字段名。(2)、定义列表框的数据源。(3)、根据所需要查的字段的数据类型初始化文本框text1。Form1的Init程序代码如下:
use &数据表名称 in 0
sele &数据表名称
n=afield(lin)
if substr(字段号表,1,1)>"9" && 如果不是填的数字,就是填的字段名
字段名=字段号表
else
for i=1 to n && 如果填的字段号,查出其字段名
if lin(i,1)=字段号表
字段名=lin(i,1)
exit
endif
endfor
endif
thisform.list1.rowsource=sele &字段名 from &数据表名称 into cursor tmp
do case
case lin(i,2)="C"
thisform.text2.value=""
case lin(i,2)="I"
thisform.text2.value=0
case lin(i,2)="N"
thisform.text2.value=0
case lin(i,2)="D"
thisform.text2.value={ - - }
endcase
2)、查询程序设计
该程序要点在于(1)、如何分析用户所选中的选项按钮“Optiongroup2”的按钮号并根据选项按钮被选中的按钮形成查询条件表达式。(2)、执行查询并显示。
显示查询按钮的Click程序代码如下:
do case
case thisform.Optiongroup2.value=1
x1=字段名+"='"+thisform.text2.value+"'"
case thisform.Optiongroup2.value=2
x1=字段名+">'"+thisform.text2.value+"'"
case thisform.Optiongroup2.value=3
x1=字段名+">='"+thisform.text2.value+"'"
case thisform.Optiongroup2.value=4
x1=字段名+"<'"+thisform.text2.value+"'"
case thisform.Optiongroup2.value=5
x1=字段名+"<='"+thisform.text2.value+"'"
case thisform.Optiongroup2.value=6
x1=字段名+"<>'"+thisform.text2.value+"'"
case thisform.Optiongroup2.value=7
x1="'"+thisform.text2.value+"'$"+字段名
endcase
sele * from &数据表名称 where &x1
说明:本例只考虑对字符型字段查询,完整设计见教材所附光盘中源程序代码。
3)、文本框的模糊查询程序设计
文本框的Interactivehange程序代码如下:
k=len(allt(this.value)) && 当前用户已输入的数据的长度
sele tmp && 初始化程序中定义的列表框的数据源临时表名tmp
loca for substr(&字段名.,1,k)=allt(this.value) &&和表中那一条数据最匹配
thisform.list1.listindex=recno() &&使列表框显示该条记录数据
thisform.list1.refresh()
*********************************************************************
为了使操作更方便,字段名与关系符也可以改用选项按钮。使用说明见程学先等著清华大学出版社出版的《Visual FoxPro程序设计》一书中附录:
2、任选字段单查询部件
界面如附录1图19所示,用户可在予选字段基础上再指定其中某一字段进行单查询。适用于查询字段预先不能唯一确定的情况。
接口参数:
数据表名称=“”
打印格式文件名称=“”
字段号表=“”
调用命令:DO FORM 单条件查询
*********************************************************************
该部件源程序见该书光盘。
可以将上述二个部件合并为一个,基于任选字段单查询部件,只要默认:在字段号表中填入的可以是一个有关字段位置的数字例如2,也可以是数字加关系符,例如2=,或2$,(利用最小系统.exe的接口参数输入程序可以帮助生成该内容,无需特别去记忆)。
如果字段号表中填入的是数字加关系符,则自动变成为去掉了选关系符的选项按钮框的附图11.27的界面。如果单一是数字,则自动变成如附图11.27的界面。这样可以减少部件的总量,部件的复用性也更强。
二、二条件查询
有些查询要求提供二个条件,条件之间用“并且”或“或者”相联系。实现界面可以是类似于上面的设计,只要将标签与文本框的组合增加一组,二组间标上“AND”或“OR”就可以了。也可以是二组组合框+组合框+文本框,程序设计方法与上面相似。
在以上设计中均未考虑选择字段输出问题,通过功能按钮,用户可以选择是以单记录格式显示或表格格式显示。如果选择输出,可以在添加选择输出字段的界面。
如果条件更多,三个或更多,设计方法可以考虑如下几种:(1)将标签与文本框的组合继续增加。首先显示二组,每当用户在最后一组中填写数据或进行选择操作时,自动再增加一组。这种方式设计起来比较麻烦,界面也不太好控制。(2)先建立一个数据表,可以在界面中只给组合框+组合框+文本框的一组组合,每当用户给出一组条件并按下添加条件按钮时,就将该条件加到数据表中,同时清掉组合框+组合框+文本框中的内容,让用户可以继续补加条件。当用户要求查询时,再根据数据表中记录的内容形成查询条件,组织查找操作。该方法能形成任意多条件的组合,但不够直观,对数据表修改、删除操作容易产生毛病、如果还要形成带括号的条件表达式更加麻烦。(3)设计一个编辑框存放组合条件,在界面中只给组合框+组合框+文本框的一组组合,每当用户给出一组条件并按下添加条件按钮时,就将该条件加到编辑中,同时清掉组合框+组合框+文本框中的内容。当用户要求查询时,直接读出编辑框中的内容组织查询。这种方法直观、易操作、容易检查与发现操作中的问题。
上一篇文章中介绍了可以根据任意多条件组合查询并选择输出的部件设计,就是按上面最后一个设计设计的。以下是又一设计方案,内容摘自:04年水利水电出版社出版的《Visual FoxPro应用基础与基于部件系统设计技术》一书,作者:程学先、曾玲、林珊、程传庆,参加该书工作的还有:金波、林珊、彭宏昊、刘伟、曾立平、程传庆、雷飞宇、程传慧、陈永辉、江南、王莉、曾玲、史函、祝苏薇、胡显波、饶昆、杨晓燕、高霞、高亮、李芳、钱涛、余晓艳、周金森、叶品菊、李莎等。
*********************************************************************
1、界面设计
界面如图
对任意表结构测试利用函数AFIELDS完成,需要定义“选字段名”组合框、选输出内容列表框等列出内容,等于全表所有字段名的集合。需要清空存放条件表达式的编辑框Text4。
生成条件表达式:查询条件由若干关系表达式和逻辑符连接构成。每个关系表达式又由与字段名有关的表达式、关系运算符及查询数值构成。对字段名和可选的关系运算符,可以提供组合框由用户选择输入,查询数值由用户根据查询要求输入。为减少输入的盲目性,可以提供一个列表框向用户展示相关字段在数据库中存储的数值情况,如其中数据可以作为查询数值,用户只需点击就可快速输入;如其中数据不含查询数值,其中数据也可作为用户输入的提示,使用户了解输入的格式与范围。
每形成一个关系表达式,要求用户按“添加条件”按钮,添加到编辑框中。由于编辑框可容纳字符数由内存大小决定,因而可使程序适应任意多条件组和的查询要求;使用编辑框也可使对数据库操作较熟悉的用户能直接修改查询条件并为“定制”作准备。
查询条件生成的操作可分为:选择字段名→对于字符型字段确定是否取子串→选关系符→输入查询条件数据值→产生逻辑表达式→加入到编辑框之中。如果前面已有逻辑表达式,将要求用户选择逻辑符使与前面的逻辑表达式相连接,用户如果未选,默认的逻辑符是AND。
内容除上述内容外还包括:(1)、当对字符类型数据查询时允许按其子集查询。例如,设学号由11位组成,其中前四位为入学年份、后四位为专业代码、第9与第10位为班级代码、末四位为顺序号。如果要按专业查询或统计,需要抽出学号的从第五个字符开始长4个字符的学号子集,再形成条件表达式。
(2)、允许对字符类型字段或备注类型字段作全文检索式查询。全文检索指只按一定格式输入要查找的字符串,不需要选择关系符就能对文本查找。本设计中约定如下:先输入检索字,注意区分大、小写。空格、&、|、-、( )、$、#、*、\ 为特殊意义字符。上述字符均应为英文字符,字符两边不要有空格。空格或& 表示要求两边内容均要包含在内。“|”“表示要求两边内容至少有一个包含在内。“- ”表示后边内容不包含在内。“( ) ”表示其内部分为整体内容。“$” 表示其后的词在标题之首,要放在全文检索词最前面。“#”表示在查找的二个词间可能有有限的若干个任意的字符,二个词间字符的个数不多于#号的个数,一个汉字等于二个#号宽。“*”表示在查找的二个词间可能有任意多个任意字符。“ ”为变义符,用在特殊字符前表示后边字符不是特殊字符,而是普通字符。
2、全文检索程序设计
当在全文检索内容文本框Text31中输入了查询检索的内容后,如果按下“添加全文检索”按钮,将自动形成条件表达式,和其他条件一起连接到条件编辑框EDIT1中。其程序设计流程图见图
【例
IF LEN(ALLT(ThisForm.b1.Text))<1
RETURN &&如果未选字段名,返回。
ENDIF
检索内容0=ALLT(ThisForm.Text31.Value) &&取检索内容在变量“检索内容0“中
并去掉空格
no=LEN(检索内容0)
IF no >1 &&如果除了$打头的之外还有内容,就再作下面的处理
RETURN &&如果未输入检索内容,返回。
ENDIF
o0=ALLT(ThisForm.Edit1.Value) &&原条件编辑框中内容
IF LEN(o0)>1 AND (! "AND" $ SUBSTR(o0,on0-5,6)) AND (! "or" $ SUBSTR(o0,on0-5,6))
ThisForm.Edit1.Value=ThisForm.Edit1.Value+" AND ("
ELSE
ThisForm.Edit1.Value= "("
ENDIF
v=ThisForm.b1.Text &&字段名存放B1中
i=1
o=””
FOR j=1 TO LEN(检索内容0)
DO CASE
CASE SUBSTR(检索内容0,i,1)=" " OR SUBSTR(检索内容0,i,1)="&"
o=o+" ' $ &v.) AND (' "
ThisForm.Edit1.Value= ThisForm.Edit1.Value+o
o=””
i=i+1
CASE j=LEN(检索内容0)
o=o+SUBSTR(检索内容0,i,1)+" ' $ &v.) "
dit1= Edit1+o
o=""
i=i+1
OTHERWISE
o=o+SUBSTR(检索内容0,i,1)
i=i+1
ENDCASE
ENDFOR
3、根据字段子集查询程序设计
【例
ed1= ThisForm.Edit1.Value &&条件编辑框原值
IF ThisForm.Spinner1.Value>0 AND ThisForm.Spinner2.Value>0 AND (leix=”C” OR leix=”M”)
no1=ThisForm.Spinner1.Value &&从第几个字节开始
no2=ThisForm.Spinner2.Value &&长几个字节
no3= ThisForm.b1.Value &&字段名
no4= ThisForm.c1.Value &&关系符
no5= ThisForm.d1.Value &&查询内容
ed1=ed1+"SUBSTR("+ALLT(no3)+","+ALLT(STR(no1))+","+ALLT(STR(no2))+")"+no4+" '"+ALLT(no5)+"'"
ELSE
IF leix<>”M” AND leix<>”G”
ed1=ed1+" "+ALLT(ThisForm.b1.Value)+ThisForm.c1.Value+"'"+ALLT(d1)+"'"
ENDIF
ENDIF
ThisForm.Edit1.Value=ed1
全表或分组统计包括分组、加入求和字段、加入求平均字段、加入求最大字段、加入求最小字段、加入求记录条数字段及加入排序字段等按钮。在有统计要求的情况下,如果在加入分组字段框中加入了字段名,将分组进行统计,否则对全表进行统计。如果在加入求和字段框中填入了字段名,输出将增加一列:某某字段和,这时如果是对全表统计,最终结果将只有一条统计记录,如果是分组统计,最终统计显示的记录条数等于组数。其他统计情况与此相似。
4、统计程序设计
【例
要求语句格式为“SUM(<字段名>) AS <字段名>和”的形式。
FOR i=1 TO linx4
IF ALLT(linx6(i,1))=ALLT(ThisForm.List5.Value)
EXIT
ENDIF
ENDFOR
IF ! (linx6(i,2)="I" OR linx6(i,2)="N" OR linx6(i,2)="C")
=MESSAGEBOX("非数值、字符类型不能作求和操作!")
ELSE
IF linx6(i,2)="C"
=MESSAGEBOX("字符类型数据中有非数字字符时求和操作将可能出错!")
IF LEN(ALLT(ThisForm.Edit2.Value))=0 && Edit2中原来为空
ThisForm.Edit2.Value="SUM(VAL("+ALLT(ThisForm.List5.Value)+")) AS "+ALLT(ThisForm.List5.Value)+"和"
ELSE
ThisForm.Edit2.Value=ThisForm.Edit2.Value+",SUM(VAL("+
ALLT(ThisForm.List5.Value)+")) AS "+ALLT(ThisForm.List5.Value)+"和"
ENDIF
ELSE
IF LEN(ALLT(ThisForm.Edit2.Value))=0
ThisForm.Edit2.Value="SUM("+ALLT(ThisForm.List5.Value)+") AS "+ALLT(ThisForm.List5.Value)+"和"
ELSE
ThisForm.Edit2.Value=ThisForm.Edit2.Value+",SUM("+
ALLT(ThisForm.List5.Value)+") AS "+ALLT(ThisForm.List5.Value)+"和"
ENDIF
ENDIF
ENDIF
Thisform.Refresh()
【例
qu1=ALLT(ThisForm.Edit2.Value)
qu2=ALLT(ThisForm.Edit1.Value)
qu3=ALLT(ThisForm.Text1.Value)
qu4=ALLT(ThisForm.Text2.Value)
IF LEN(qu1)=0
qu1=" * "
ENDIF
IF LEN(qu2)=0
=MESSAGEBOX("请注意:您未输入查询条件!查询结果是表的全集。")
qu2=" RECNO()>0 "
ENDIF
DO CASE
CASE LEN(qu3)>0 AND LEN(qu4)>0
SELE &qu1. FROM &linx7. WHERE &qu2. GROUP BY &qu3. ORDER BY &qu4. INTO DBF&Name3
CASE LEN(qu3)>0
SELE &qu1. FROM &linx7. WHERE &qu2. GROUP BY &qu3. INTO DBF&Name3
CASE LEN(qu4)>0
SELE &qu1. FROM &linx7. WHERE &qu2. ORDER BY &qu4. INTO DBF&Name3
OTHERWISE
SELE &qu1. FROM &linx7. WHERE &qu2. INTO DBF&Name3
ENDCASE
SELE &Name3
5、定制功能的实现
程序员在生成查询表达式后,定制功能使他能将该表达式存储起来,并向用户提供具有较简单查询界面的程序,用户再查询时,使用这样的查询程序只需修改查询数据值,生成条件表达式的操作将变简单。
【例
qu1=ALLT(ThisForm.Edit2.Value)
qu2=ALLT(ThisForm.Edit1.Value)
qu3=ALLT(ThisForm.Text1.Value)
qu4=ALLT(ThisForm.Text2.Value)
IF LEN(qu1)=0
qu1=" * "
ENDIF
IF LEN(qu2)=0
qu2=" RECNO()>0 "
ENDIF
DO CASE
CASE LEN(qu3)>0 AND LEN(qu4)>0
o="SELE &qu1. FROM &linx7. WHERE &qu2. GROUP BY &qu3. ORDER BY &qu4. INTO DBF &Name3."
CASE LEN(qu3)>0
o="SELE &qu1. FROM &linx7. WHERE &qu2. GROUP BY &qu3. INTO DBF &Name3."
CASE LEN(qu4)>0
o="SELE &qu1. FROM &linx7. WHERE &qu2. ORDER BY &qu4. INTO DBF &Name3."
OTHERWISE
o="SELE &qu1. FROM &linx7. WHERE &qu2. INTO DBF &Name3."
ENDCASE
SELE 定制表
APPE BLAN
REPL 序号 WITH RECNO(), 语句 WITH o,源表名 WITH linx7,格式表单名 WITH &linx5,字段表 WITH qu1,表单名 WITH "完全查询"
=MESSAGEBOX("请记载:本定制序号为:"+STR(序号))
*******************************************************************
该设计中关于条件表达式增加了:(1)可以根据子项进行查询,例如数据表中存在日期时间类型的字段,可以根据年或月或日或它们的组合提出查询条件;又例如,如果学号由14位组成,其中前4位为入学年份、再5位为学校代码……,可以选择其子项进行查询。(2)可以利用目前各种搜索网站类似的搜索字词方式输入搜索内容,再进行查询。另外,还增加了定制功能,实际是让它能作为一中开发工具,程序员的手工操作将被记录下来,并形成程序输出给程序员,程序员可以复制到关于该部件界面简单化后的程序中交用户使用,使用户操作简化。
该部件还可以增加默认处理,根据接口参数中输入的内容,产生前述各个部件的界面,提供它们所能提供的功能。如果在部件库中准备了各种简单的、复杂的;变化小、变化大的不同部件,将使我们之后的设计有更多的选择。设计复杂的部件功能强,自适应性好,但程序设计复杂、冗余代码多、使用难度大。
更复杂的查询部件见前述清华大学出版社《Visual FoxPro程序设计》一书附录:
*****************************************************************
5、带聚集函数组合查询
界面如附录1图20所示。该程序在组合查询基础上可进一步根据统计值形成查询条件,例如求分数总和大于500,分数平均大于70等条件的查询。
操作时前面步骤与组合查询相同,在选字段后如果点击“加入求和字段”或“加入求平均字段”并且如果选关系符,输入有关数据,例如前文中的500或70,再点击“添加涉及聚集函数条件”的按钮,就会形成新的条件加入到下面的编辑框中。再之后输出方式与组合查询相同。
接口参数:数据表名称,打印格式文件名称,相关表名称,外关键字
调用命令:DO FORM 带聚集函数组合查询
***********************************************************
该设计的查询条件可以进一步包括由聚合函数构成的条件,例如求总分大于600的学生数据等。同样,通过接口参数变化,在实际调用时,可以形成面向用户的较简单的界面。
在实际设计系统时,程序员可以根据需求灵活选择部件使满足需求。对于大多数系统而言,如果设计只涉及一个表(可以包括相关的代码表)的查询,以上部件一般都可以足够满足需要了。
Archiver|手机版|科学网 ( 京ICP备07017567号-12 )
GMT+8, 2024-12-5 10:19
Powered by ScienceNet.cn
Copyright © 2007- 中国科学报社