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

SqlDelight ON CONFLICT DO UPDATE 抛出near "ON"语法错误求助

问题产生原因

dialect = "sqlite:3.25"配置仅作用于SqlDelight的编译期语法检查阶段,不会将高版本SQLite的能力打包进应用,运行时Android端默认调用系统内置的SQLite实现,而系统内置SQLite版本与API等级强绑定:

  • API 30(Android 11)及以上版本内置SQLite版本为3.28+,原生支持INSERT ... ON CONFLICT DO UPDATE(UPSERT)语法,因此运行正常
  • API 29及以下版本内置SQLite版本最高为3.22,未实现该UPSERT语法,执行时会直接抛出语法错误,这就是低版本设备崩溃的核心原因。

你遇到的near "ON": syntax error报错,就是低版本SQLite解析器不认识ON CONFLICT DO UPDATE结构导致的,语句中用到的excluded关键字同样是SQLite 3.25新增特性,低版本也无法识别。

可行解决方案

根据项目实际需求选择以下任意一种方案即可:

  • 方案1:打包高版本SQLite到应用中,脱离系统内置SQLite版本限制
    引入支持bundled模式的Android SQLite驱动(AndroidX SQLite、Requery SQLite均可),初始化SqlDelight时替换默认的系统SQLite驱动为打包了高版本SQLite二进制的驱动实例,全API等级下运行的SQLite版本统一为3.25+,原有SQL语句不需要做任何修改即可正常运行。SqlDelight 1.5.3版本对这类自定义驱动的支持已经完善,不需要额外升级SqlDelight版本。
  • 方案2:改写SQL逻辑兼容低版本SQLite,不引入额外依赖
    放弃使用ON CONFLICT DO UPDATE语法,改用低版本原生支持的逻辑实现UPSERT效果:
    • 若表结构简单、所有字段都会在插入时赋值,可以直接用INSERT OR REPLACE语法替代,注意该语法会在冲突时删除旧行再插入新行,未赋值的字段会被重置为默认值
    • 如果只需要更新部分字段,推荐用事务包裹逻辑:先尝试执行普通INSERT语句,捕获唯一键冲突异常后再执行UPDATE语句更新目标字段,更新时直接传入对应参数,不要使用excluded关键字,这种方式不会丢失原有行的其他字段数据,全API版本兼容。
  • 方案3:调整最低支持版本
    如果项目不需要覆盖API 29及以下的用户,直接将Android模块的minSdkVersion调整为30,直接使用系统内置的高版本SQLite即可,不需要修改代码或依赖。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.02 00:03:49