You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Delphi新手求助:如何从.ini文件执行动态SQL查询?

Delphi动态执行INI文件中带IN条件的查询

需求说明

作为Delphi编程新手,需实现以下功能:

  • 从DBGrid中选择若干文件名,确认后点击按钮执行查询
  • 查询语句存储在.ini文件中,需根据每次选择的不同文件名动态生成正确的IN子句

现有文件与代码

Queries.ini内容

[Query]
QSELECTEDFN=SELECT * FROM TEST_01 WHERE FILE_NAME IN (:FILE_NAME);

当前Delphi代码

ini := TIniFile.Create('C:\file dir\Queries.ini');
try
  qSlctdByFN := ini.ReadString('QUERY', 'QSELECTEDFN', '');
  ADOQuery1.SQL.Clear;
  ADOQuery1.SQL.Text := qSlctdByFN;
  ADOQuery1.Parameters.ParamByName('FILE_NAME').Value := slselectedFN.CommaText;
  ADOQuery1.Active := true;
finally
  ini.Free;
end;

期望执行结果

  • 选择1.txt、2.txt时,执行SQL:
SELECT * FROM TEST_01 WHERE FILE_NAME IN ('1.txt','2.txt');
  • 仅选择3.txt时,执行SQL:
SELECT * FROM TEST_01 WHERE FILE_NAME IN ('3.txt');

问题分析

当前代码的核心问题是:将slselectedFN.CommaText直接赋值给单个参数,会让数据库把'1.txt,2.txt'当成单个文件名去匹配,而非两个独立的文件名,无法得到预期结果。

解决方案

方案一:参数化动态生成占位符(推荐,安全无注入风险)

这种方式通过动态生成对应数量的参数占位符,再逐个赋值,完全符合参数化查询的规范,避免SQL注入问题。

步骤1:修改INI文件的SQL模板

将原语句改为带占位标记的模板,方便后续替换:

[Query]
QSELECTEDFN=SELECT * FROM TEST_01 WHERE FILE_NAME IN ({PARAMS});

步骤2:修改Delphi代码

var
  ini: TIniFile;
  baseSQL: string;
  i: Integer;
  paramPlaceholders: string;
begin
  ini := TIniFile.Create('C:\file dir\Queries.ini');
  try
    baseSQL := ini.ReadString('QUERY', 'QSELECTEDFN', '');
    paramPlaceholders := '';
    
    // 根据选中文件数量生成参数占位符(如:FN1, :FN2)
    for i := 0 to slselectedFN.Count - 1 do
    begin
      if i > 0 then
        paramPlaceholders := paramPlaceholders + ', ';
      paramPlaceholders := paramPlaceholders + Format(':FN%d', [i+1]);
    end;
    
    // 替换模板中的占位标记
    baseSQL := StringReplace(baseSQL, '{PARAMS}', paramPlaceholders, [rfReplaceAll]);
    
    ADOQuery1.SQL.Clear;
    ADOQuery1.SQL.Text := baseSQL;
    
    // 为每个参数赋值
    for i := 0 to slselectedFN.Count - 1 do
    begin
      ADOQuery1.Parameters.ParamByName(Format('FN%d', [i+1])).Value := slselectedFN[i];
    end;
    
    ADOQuery1.Active := True;
  finally
    ini.Free;
  end;
end;

方案二:拼接带引号的文件名(不推荐,存在SQL注入风险)

如果是内部可控系统,且文件名不会包含特殊字符,可使用这种方式,但需注意转义单引号:

步骤1:修改INI文件的SQL模板

[Query]
QSELECTEDFN=SELECT * FROM TEST_01 WHERE FILE_NAME IN (%s);

步骤2:修改Delphi代码

var
  ini: TIniFile;
  sqlTemplate: string;
  fileNamesStr: string;
  i: Integer;
begin
  ini := TIniFile.Create('C:\file dir\Queries.ini');
  try
    sqlTemplate := ini.ReadString('QUERY', 'QSELECTEDFN', '');
    fileNamesStr := '';
    
    // 拼接带单引号的文件名,转义内部的单引号
    for i := 0 to slselectedFN.Count - 1 do
    begin
      if i > 0 then
        fileNamesStr := fileNamesStr + ', ';
      fileNamesStr := fileNamesStr + '''' + StringReplace(slselectedFN[i], '''', '''''', [rfReplaceAll]) + '''';
    end;
    
    ADOQuery1.SQL.Clear;
    ADOQuery1.SQL.Text := Format(sqlTemplate, [fileNamesStr]);
    ADOQuery1.Active := True;
  finally
    ini.Free;
  end;
end;

总结

优先使用方案一,参数化查询不仅能正确匹配多个文件名,还能杜绝SQL注入风险,是数据库操作的标准安全做法。

内容的提问来源于stack exchange,提问作者Hoon Heo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 21:28:15