FireDAC执行SQLite含row_number()查询报near '('语法错误
问题原因
报错的核心原因是当前FireDAC加载的SQLite引擎版本低于3.25.0:
row_number() OVER (...)窗口函数是SQLite 3.25.0(2018年9月发布)才新增的语法特性,低版本SQLite的SQL解析器无法识别OVER关键字,解析到row_number()后的括号位置时就会直接抛出语法错误。- FireDAC默认内置了静态链接的旧版SQLite库,如果没有手动配置,大概率会加载自带的低版本引擎,哪怕系统中安装了新版SQLite也不会自动调用。
- 你SQL中
Compte AS [Compte::Varchar(10)]是FireDAC原生支持的字段类型映射语法,会在FireDAC内部预处理,不会传递给SQLite引擎,和本次报错无关。
修复方案
根据实际部署场景二选一即可:
- 优先方案:升级SQLite引擎到3.25.0以上版本
- 下载3.25.0及以上版本的
sqlite3.dll,放到程序可执行文件同目录 - 配置TFDConnection的连接参数,强制FireDAC加载外部新版dll,禁用内置静态库:在连接参数中新增
SQLiteAdvanced=forceembedded=no,代码配置示例:
FDConnection1.Params.Add('SQLiteAdvanced=forceembedded=no');- 建立连接后执行
SELECT sqlite_version();验证当前加载的引擎版本,确认版本号≥3.25.0后,原SQL语句即可正常执行。
- 下载3.25.0及以上版本的
- 兼容方案:无法升级SQLite版本时改写SQL兼容低版本
如果部署环境限制不能替换SQLite库,可以用关联子查询改写行号逻辑,兼容所有SQLite 3版本,改写后SQL如下:
注意:该写法依赖关联子查询统计行号,数据量较大时查询性能明显低于原生窗口函数,仅作为兼容场景的备选方案。SELECT (SELECT COUNT(*) FROM R1 t2 WHERE t2.Men7a_Row <= t1.Men7a_Row AND t2.Men7a_Date BETWEEN :DS AND :DF) AS RowNum, t1.Nom_Prénom, t1.Compte AS [Compte::Varchar(10)], t1.Men7a_Value, t1.Men7a_Date FROM R1 t1 WHERE t1.Men7a_Date BETWEEN :DS AND :DF ORDER BY t1.Men7a_Row LIMIT 25 OFFSET 25;
内容的提问来源于stack exchange,提问作者Djemoui
相关产品推荐
相关产品推荐

