当前位置:首页 > 问答 > 正文

Delphi里用DBGrid查数据库那些事儿,快速搞定实用查询小技巧分享

Delphi里用DBGrid查数据库那些事儿,快速搞定实用查询小技巧分享

(根据网上程序员们的经验贴和论坛讨论整理)

哥们儿,搞Delphi的,十个有九个都得跟DBGrid和数据库打交道,别看这玩意儿就是个表格,真想让它听话,快速查出你想要的数据,没点小技巧还真不行,今天咱就不整那些高大上的理论,直接上干货,聊聊怎么让DBGrid的查询变得又快又省心。

基础中的基础:SQL语句要溜

DBGrid本身只是个显示工具,真正干活的是背后的查询语句,通常就是SQL,你想啊,你要是跟数据库都说不明白话,DBGrid能给你显示对东西吗?所以第一步,得把SQL练熟。

  • 模糊查询是王道:用户输入个关键字就想搜,这是最常见的需求,别想复杂了,就用SQL的LIKE关键字,比如查客户表中名字带“北京”的客户,SQL可以这么写:SELECT * FROM Customers WHERE CustomerName LIKE '%北京%',那个是通配符,代表任意字符,百分号在前面(%关键字)会导致数据库进行全表扫描,如果数据量巨大,可能会慢,但对几千几万条数据来说,够用了。
  • 参数化查询,安全又高效:这是老程序员血与泪的教训!千万别用字符串拼接的方式把用户输入的内容直接塞到SQL里,比如SQL.Text := 'SELECT * FROM Users WHERE Name = "' + Edit1.Text + '"',这简直是给SQL注入攻击大开方便之门!正确的姿势是用参数化查询,以常用的TADOQuery为例,你可以把SQL写成:SELECT * FROM Users WHERE Name = :UserName,然后在代码里给参数赋值:ADOQuery1.Parameters.ParamByName('UserName').Value := Edit1.Text;,这样做,数据库引擎会处理好特殊字符,既安全,有时候还能提升查询效率(因为数据库可以缓存执行计划)。

让DBGrid本身更“好用”

光查出来还不行,还得让用户看着舒服,找着方便。

  • 标题栏点一下就排序:这个功能太实用了!用户希望点一下DBGrid的列标题,数据就按那列排序,实现起来不难,通常是在DBGrid的OnTitleClick事件里写代码,原理就是动态改变查询的ORDER BY子句。
    procedure TForm1.DBGrid1TitleClick(Column: TColumn);
    var
      FieldName: string;
    begin
      FieldName := Column.FieldName; // 获取点击的字段名
      // 假设之前已经按这个字段升序了,现在就降序,反之亦然
      if ADOQuery1.IndexFieldNames = FieldName then
        ADOQuery1.IndexFieldNames := FieldName + ' DESC'
      else
        ADOQuery1.IndexFieldNames := FieldName;
      // 或者更常见的,重新设置SQL的Order By部分,然后重新Open查询
    end;

    具体实现方式可能因使用的数据集组件(TADOQuery, TFDQuery等)略有不同,但思路都是一样的:改排序条件,重新查询。

  • 边输入边搜索(即时搜索):不要让用户输完完整的关键字再点“查询”按钮,在输入框(比如TEdit)的OnChange事件里就开始查,体验会好很多,要注意性能问题,不能每次按键都查询,可以加个TTimer,用户停止输入一段时间(比如300毫秒)后再触发查询,这就是常说的“防抖”(Debounce)。
  • DBGrid里直接高亮关键行:想让查询结果中符合条件的数据行更醒目吗?用DBGrid的OnDrawColumnCell事件,在这个事件里,你可以判断当前行的数据是否符合某个条件,然后改变单元格的背景色或字体颜色,把所有金额大于10000的单元格背景设为浅黄色:
    procedure TForm1.DBGrid1DrawColumnCell(Sender: TObject; const Rect: TRect;
      DataCol: Integer; Column: TColumn; State: TGridDrawState);
    begin
      if (Column.Field.FieldName = 'Amount') and (Column.Field.AsFloat > 10000) then
      begin
        DBGrid1.Canvas.Brush.Color := clYellow;
        DBGrid1.Canvas.FillRect(Rect);
        DBGrid1.Canvas.TextOut(Rect.Left + 2, Rect.Top + 2, Column.Field.AsString);
      end;
    end;

性能优化的小心思

数据量大了,查询慢怎么办?除了给数据库表加索引这种后端操作,前端也能做些事。

  • 只查需要的字段:别动不动就SELECT *,把需要的字段名明确写出来,比如SELECT ID, Name, Phone FROM Customers,网络传输的数据量小了,速度自然就快了。
  • 合理设置数据集的Fetch操作:像TFDQuery(FireDAC)这样的高级组件,有FetchOptions属性,可以设置一次从数据库取多少条记录(RowsetSize),如果数据量超大,可以考虑分页查询,别一次性把几万条数据都拽到内存里,DBGrid会卡,程序也容易爆内存。

别忘了异常处理

数据库操作最容易出幺蛾子,网络断了、表被锁了、SQL写错了……你的“查询”按钮的点击事件,一定要放在try...except块里。

procedure TForm1.btnSearchClick(Sender: TObject);
begin
  try
    ADOQuery1.Close;
    ADOQuery1.SQL.Text := '你的查询SQL';
    // ...设置参数...
    ADOQuery1.Open;
  except
    on E: Exception do
      ShowMessage('查询出错啦:' + E.Message); // 给用户一个友好的提示
  end;
end;

玩转DBGrid查询,核心思路就是“SQL精准 + 交互友好 + 性能可控”,多练练手,把这些小技巧融入到你的代码里,慢慢就会发现,处理数据库查询也就是那么点儿事儿,没啥神秘的,希望这些来自实践的经验对你有帮助!

Delphi里用DBGrid查数据库那些事儿,快速搞定实用查询小技巧分享