[返回]
计算机世界2000年第33期

在Delphi中实现多重查询

广东省农业管理干部学院 陈建兵

  在数据库管理系统中,查询的方式主要有以下几种:1.固定字段的单一查询。2.可选择字段的单一查询。3.限制若干个字段的多重查询。4.可任意选择字段的多重查询。前两种也称为单条件查询,后两种称为多重(或多条件)查询。在实际中,系统(实为程序员)提供给用户的查询方式以单条件查询为多,即使提供了多条件方式,通常也只有两或三个条件,因为编写多重查询是一项非常棘手且烦琐的事情。实际上,利用表格Grid功能,就能轻松地实现多重查询。本人以Delphi为例,介绍具体的实现方法。这种思想,也同样适合于其他的编程语言(如Visual Foxpro)。

  程序主要按如下三个功能来实现:

  1. 设置DBGrid;

  2. 生成查询条件(语句);

  3. 执行查询。

  具体步骤如下:

  ⑴新建一工程文件,取名为PDBGrid.dpr;

  ⑵给单元文件取名为UDBGrid.pas,在其相应的表单(取名为frmDBGrid)中添加如下控件并编写相应的代码:

  其中Table2(记录查询条件的数据集)对应的表 CxComm.db的结构定义如下:

  表单的FormActivate事件代码如下:

procedure TfrmDBGrid.FormActivate(Sender: TObject);
begin
  if Table2.Active then Table2.Close;
  Table2.EmptyTable; //清空条件
  Table1.Open;
  Table2.Open;
end;

  Button1(设置DBGrid)的Click事件代码如下:
procedure TfrmDBGrid.Button1Click(SenderTObject);
begin
  MySetDBGrid(Table1,DBGrid2); 
  // MySetDBGrid为自定义过程
  //以Table1为数据源,DBGrid2为记录筛选(查询)条件的表格
end;

    Button2(生成查询)的Click事件代码如下:
procedureTfrmDBGrid.Button2Click(Sender:TObject);
begin
 if MyCreate_SQL(Table1,Table2,Query1) 
   //MyCreate_SQL为自定义函数
   //由指定数据来源表生成SQL,存入Query1
  then begin
    Memo1.Lines.Clear;
    Memo1.Lines:=(Query1.SQL);
   Memo1.Modified:=false;
  end
end;

    Button3(执行查询)的Click事件代码如下:
procedureTfrmDBGrid.Button3Click(Sender:TObject);
begin
  with Query1,SQL do
   begin
    Close;
    if Memo1.Modified //用户可修改SQL语句
     then SQL:=Memo1.Lines;
    try
     ExecSQL;
     Open;
    except //捕捉错误并处理
     begin
      MessageBeep(0);
      Application.MessageBox(‘错误的SQL语句!',
     ‘确认',MB_OK+MB_ICONSTOP);
      Close;
     end;
    end //try
   end;
end; //执行SQL

  自定义过程MySetDBGrid (设置DBGrid)的代码如下:

procedure TfrmDBGrid.MySetDBGrid
  (sTable:TTable;tjDBGrid:TDBGrid);
  //参数说明:sTable为数据(包括字段、记录)来源表
  //   tjDBGrid为记录筛选(查询)条件的表格
var i:byte;
begin
    //设置查询项目
  if not sTable.Active then sTable.Open;
  tjDBGrid.Columns[0].PickList.Clear;
  for i:=0 to sTable.FieldCount-1 do 
   //记录数(即字段数)
   begin
   tjDBGrid.Columns[0].PickList.Add
   (sTable.Fields[i].FieldName);
   end; //for
   //设置关系(=,<>,>,>=,<,<=) 及逻辑(AND,OR)
  tjDBGrid.Columns[1].PickList.Text:=‘='+#13+
‘<>'+#13+‘>'+#13+‘>='+#13+‘<'+#13+
‘<=';tjDBGrid.Columns[3].PickList.Text:=‘AND'+#13+
 ‘OR';
end;//设置DBGrid

  自定义函数MyCreate_SQL (生成查询)的代码如下:

function TfrmDBGrid.MyCreate_SQL
(sTable,tjTable:TTable;tjQuery:TQuery):boolean;
  //参数说明:sTable为数据(包括字段、记录)来源表
  // tjTable为记录筛选(查询)条件的表
  // tjQuery记录SQL语句
var i:byte;
 lsDate:TDate; //检测日期格式用
 sLj,sFilter,sFieldName:string;
  //分别表示:逻辑关系、筛选条件、字段名
begin
  Result:=true;
    //生成“筛选条件"语句
  with tjQuery,SQL do
   begin Close;
    Clear;
DatabaseName:=sTable.DatabaseName; 
 //设置Query1的别名
   Add(‘Select * from '+sTable.TableName);
   end;
   with tjTable do //查询(筛选)条件表
   begin
   if not Active then Open;
   if IsEmpty
   then begin
      Application.MessageBox(‘未选择筛选条件!',
    ‘确定',MB_OK+MB_ICONEXCLAMATION);
        Exit;
      end;
    tjQuery.SQL.Add(‘Where ');//含有筛选条件
    sFilter:=‘'; //临时记录筛选条件
    First;
    for i:=0 to RecordCount-1 do
     begin
      sLj:=Fields[3].AsString; //逻辑关系AND,OR
         //(字段名0>1实际值2)
      sFilter:=sFilter+‘(';
      sFilter:=sFilter+Fields[0].AsString+
        Fields[1].AsString;
      sFieldName:=Fields[0].AsString;
        //取第1列的字段名
 case Table1.FieldByName(sFieldName).DataType of
        ftString: begin //字符型处理
        sFilter:=sFilter+“”+Fields[2].AsString+“”
         //第2列为关系
         end;
        ftFloat, //浮点型处理
        ftAutoInc, //自增型
        ftSmallInt, //短整型
        ftInteger, //整型
        ftCurrency: begin //货币型
          sFilter:=sFilter+Fields[2].AsString;
         end;
        ftDate: begin //日期型处理
         try
          lsDate:=StrToDate(Fields[2].AsString);
      sFilter:=sFilter+“”+FormatDateTime
    (‘mm/dd/yyyy',StrToDate(Fields[2].AsString))+“”;
         except
      Application.MessageBox(‘错误的日期格式!’,
       ‘确认',MB_OK+MB_ICONSTOP);
          Result:=false; //返回错误标志
          break;
         end;//try 日期格式判断
         end;
          //此处可增加对其他类型数据的处理
       end;//case
      sFilter:=sFilter+‘)';
      if sLj<>‘'
       then begin
         if RecNo<>RecordCount //且“非最后行"的记录
         then sFilter:=sFilter+Fields[3].AsString; 
          //And|Or;
        end
       else break;
      Next
     end;
   end; //not IsEmpty(筛选)非空
  tjQuery.SQL.Add(sFilter); //保存查询条件
end; //处理筛选条件

  另外,需要进行如下说明:

	   ...
  Type
	   ...
procedure MySetDBGrid(sTable:TTable;
  tjDBGrid:TDBGrid);
function MyCreate_SQL(sTable,tjTable:
      TTable;tjQuery:TQuery):boolean;
private
     { Private declarations }
	   ...

  值得说明的是,⑴为简化程序,逻辑关系只提供了AND 和OR两种,但为了允许用户修改SQL语句,如:在多条件之间增加括号来改变运算顺序等,增加了Memo控件;⑵在实际系统中,为方便用户的操作,可增加几个Button(按钮),功能分别是对Table2的“增加”、“删除”,这样用户界面会更友好些。

  利用这种方法来设置查询,条件个数是无限制的,且在屏幕上不会占据太大的空间,程序员实现起来要简单得多了。

  软件环境:中文Win98/中文Delphi5.0。