Delphi 10.4中SQLite3查询返回0条记录,是否为日期格式问题?
解决Delphi 10.4中SQLite日期筛选返回空结果的问题
问题根源
你的代码存在两个核心问题导致查询无结果:
SQL语法错误:缺少日期字符串的单引号
直接拼接DateToStr(d1)的结果会生成类似这样的SQL:select * from labs where ldate Between 2022-09-01 and 2022-12-31SQLite会把
2022-09-01解析为数字运算(2022减9减1=2012),而非日期字符串,自然匹配不到任何记录。日期格式依赖系统区域,不匹配SQLite要求
即便你设置了DateTimePicker的显示格式,DateToStr仍会使用系统短日期格式(比如MM/dd/yyyy),生成的字符串不符合SQLite的yyyy-MM-dd规范,导致日期匹配失败。
另外,代码里SELECT *搭配GROUP BY ldate, ltestname的逻辑也有问题:SQLite默认允许非聚合字段不在GROUP BY中,但会返回不确定的结果,且你在SQLiteStudio测试的语句并未添加GROUP BY,这也可能导致结果不一致。
解决方案
方案1:使用参数化查询(推荐,安全且避免格式问题)
参数化查询会自动处理日期类型转换,无需手动拼接字符串和引号,同时能防止SQL注入:
if cbResultDisplaySelect.ItemIndex = 1 then begin d1 := DateTimePicker1.Date; d2 := DateTimePicker2.Date; mmdata.labRstQry.Active := false; mmdata.labRstQry.SQL.Clear; mmdata.labRstQry.SQL.Add('select ldate, ltestname, [其他需要的字段] from labs '); mmdata.labRstQry.SQL.Add('where ldate Between :StartDate and :EndDate'); mmdata.labRstQry.SQL.Add('group by ldate, ltestname order by ltestname, ldate DESC'); // 设置参数 mmdata.labRstQry.ParamByName('StartDate').AsDate := d1; mmdata.labRstQry.ParamByName('EndDate').AsDate := d2; mmdata.labRstQry.Active := true; end else...
注意:将SELECT *改为明确指定需要的字段,与GROUP BY的字段对应,避免不确定的结果。
方案2:手动拼接正确格式的日期字符串(不推荐,存在SQL注入风险)
如果一定要拼接字符串,需用FormatDateTime指定yyyy-MM-dd格式,并给日期加上单引号:
if cbResultDisplaySelect.ItemIndex = 1 then begin d1 := DateTimePicker1.Date; d2 := DateTimePicker2.Date; mmdata.labRstQry.Active := false; mmdata.labRstQry.SQL.Clear; mmdata.labRstQry.SQL.Add('select ldate, ltestname, [其他需要的字段] from labs '); mmdata.labRstQry.SQL.Add('where ldate Between ''' + FormatDateTime('yyyy-MM-dd', d1) + ''' and ''' + FormatDateTime('yyyy-MM-dd', d2) + ''''); mmdata.labRstQry.SQL.Add('group by ldate, ltestname order by ltestname, ldate DESC'); mmdata.labRstQry.Active := true; end else...
这里用两个单引号表示SQL中的一个单引号,确保日期字符串被正确包裹。
额外检查
- 确认
ldate字段在SQLite中是DATE类型,或存储为yyyy-MM-dd格式的字符串。 - 测试时可先去掉GROUP BY语句,查看是否能查询到结果,再逐步添加分组逻辑,确认分组条件是否过滤了所有数据。
内容的提问来源于stack exchange,提问作者K Boykin
相关产品推荐
相关产品推荐

