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

SQLDelight MySQL方言能否绕过语法检查支持未识别表达式?

SQLDelight MySQL方言绕过JSON函数语法检查的实现方案

针对你需要执行带JSON_OBJECT的迁移语句、不需要结果映射回Kotlin层的场景,不需要扩展方言实现,也不用在Kotlin层做数据转换,直接用以下两种方案即可:

  • 使用驱动原生执行API透传SQL
    SQLDelight底层驱动提供了跳过编译期语法解析的原始语句执行接口,整段SQL会直接下发给MySQL执行,完全不会触发SQLDelight的方言语法校验。因为你的迁移语句不需要返回结果集映射,这个方案实现成本最低。
    参考实现代码:
    driver.execute(
        identifier = null,
        sql = "INSERT IGNORE INTO new_table SELECT id, a, b, JSON_OBJECT('c', c, 'd', JSON_OBJECT(...)) FROM old_table WHERE id = ?",
        parameterCount = 1
    ) {
        bindLong(0, targetRecordId) // 按占位符顺序绑定参数,索引从0开始
    }
    
    注意:MySQL原生不支持INSERT OR IGNORE语法,需要替换为INSERT IGNORE,否则语句下发到MySQL后会报语法错误。
  • 在.sq文件中标记跳过语句校验
    如果你想保留SQLDelight自动生成参数绑定代码的能力,可以在.sq文件中对应语句前加校验跳过注释,SQLDelight生成代码时不会校验该语句的语法合法性,但依然会正常生成带参数绑定的调用方法:
    -- @sqldelight:skip-validation
    migrateOldToNew:
    INSERT IGNORE INTO new_table SELECT id, a, b, JSON_OBJECT('c', c, 'd', JSON_OBJECT(...)) FROM old_table WHERE id = ?;
    
    编写完成后正常编译项目,就可以像调用其他SQLDelight生成的方法一样调用migrateOldToNew(id)方法执行迁移。

不建议选择Kotlin层查询旧表、转换后写入新表的方案:一方面迁移效率远低于单条SQL执行,数据量较大时会产生不必要的内存和网络IO开销;另一方面Kotlin层手动组装JSON很容易出现特殊字符转义、null值处理不一致的问题,稳定性不如MySQL原生JSON函数。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 06:09:23