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

Android Kotlin项目SQLDelight新增表时非空数据库报无表错误

问题:SQLDelight新增表在已有数据的数据库中触发“No such table”错误

我用Kotlin+SQLDelight开发Android应用,新增.sq表定义后,仅在数据库已有数据时操作新表会报“No such table”错误,但空数据库下完全正常。

环境信息

  • Kotlin版本:1.8.0
  • SQLDelight版本:2.0.0
  • Gradle配置:
databases {
    register("TestDatabase") {
        packageName.set("com.test.app.db")
        verifyMigrations.set(true)
    }
}
  • SQLDelight驱动配置代码:
fun provideSqlDriver(context: Context): AndroidSqliteDriver =
    AndroidSqliteDriver(
        schema = DanaosDatabase.Schema,
        context = context,
        name = "test-db",
        callback = object : AndroidSqliteDriver.Callback(TestDatabase.Schema) {
            override fun onConfigure(db: SupportSQLiteDatabase) {
                super.onConfigure(db)
                setPragma(db, "JOURNAL_MODE = WAL")
                setPragma(db, "SYNCHRONOUS = 1")
                setPragma(db, "JOURNAL_SIZE_LIMIT = 6144000")
            }

            private fun setPragma(db: SupportSQLiteDatabase, pragma: String) {
                val cursor = db.query("PRAGMA $pragma")
                cursor.moveToFirst()
                cursor.close()
            }
        }
    )

fun provideDatabase(
    driver: SqlDriver,
): TestDatabase =
    TestDatabase(
        driver = driver
    )
  • 新表定义示例(.sq文件):
CREATE TABLE IF NOT EXISTS NewTable (
    id INTEGER PRIMARY KEY,
    name TEXT NOT NULL
);

已尝试但无效的方案

  • 清理并重建Android Studio项目
  • 确认.sq文件位置、格式正确
  • 检查SQLDelight生成的Kotlin代码无异常
  • 添加SQLDelight迁移脚本(2.sqm),问题依旧

解决方案

1. 修正迁移脚本的写法

SQLDelight迁移脚本不需要加IF NOT EXISTS,因为迁移是针对旧版本数据库执行的,旧库中必然没有新表。错误的IF NOT EXISTS会导致SQLDelight的schema验证不通过,进而跳过表创建逻辑:
假设原数据库版本为1,新增表后版本升为2,在src/main/sqldelight/com/test/app/db/目录下创建2.sqm文件,内容改为:

-- 从版本1升级到版本2
CREATE TABLE NewTable (
    id INTEGER PRIMARY KEY,
    name TEXT NOT NULL
);

2. 统一Schema引用

原配置中同时出现了DanaosDatabase.Schema和TestDatabase.Schema,这会导致迁移逻辑混乱,必须统一为同一个Schema:

fun provideSqlDriver(context: Context): AndroidSqliteDriver =
    AndroidSqliteDriver(
        schema = TestDatabase.Schema, // 修正为统一的Schema引用
        context = context,
        name = "test-db",
        callback = object : AndroidSqliteDriver.Callback(TestDatabase.Schema) {
            // 原有onConfigure代码不变
        }
    )

3. 验证迁移执行状态

在Callback中添加onUpgrade方法,确认迁移是否被触发:

override fun onUpgrade(db: SupportSQLiteDatabase, oldVersion: Int, newVersion: Int) {
    super.onUpgrade(db, oldVersion, newVersion)
    Log.d("DB_MIGRATION", "执行迁移:从版本$oldVersion 到 $newVersion")
}

如果日志未打印,说明数据库版本号未正确递增,需检查SQLDelight生成的TestDatabase.Schema.version是否符合预期。

4. 强制同步Schema与迁移脚本

开启verifyMigrations.set(true)后,SQLDelight会严格校验迁移脚本是否能将旧Schema升级为新Schema。如果编译时出现验证错误,需:

  • 确保.sq文件中的表定义和迁移脚本的创建语句完全一致(字段类型、约束、索引等)
  • 检查是否遗漏了其他Schema变更(如字段新增、约束修改)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 17:07:39