android - 将数据复制到新表时 NOT NULL 约束失败

标签 android sql sqlite android-room

我将数据库从 SQLiteOpenHelper 迁移到 Room。

我有一个想要更改的表格,我们将其命名为“my_table”。 其简化的创建语句:

CREATE TABLE `my_table`
 (`_id` INTEGER PRIMARY KEY AUTOINCREMENT,
  `title` TEXT
 )

在升级期间以及其他更改期间,我添加了新列type INTEGER NOT NULL(我还添加了外键并进行了其他重大更改,这就是创建新表而不是更改的原因现有的):

CREATE TABLE "new_table" 
 (`_id` INTEGER PRIMARY KEY AUTOINCREMENT,
  `title` TEXT,
  `type` INTEGER NOT NULL
 )

然后我想将数据从 my_table 复制到 new_table 并设置 type 列的值。

SQL语句:

INSERT INTO new_table (title) 
SELECT title FROM my_table;
UPDATE new_table SET type = 1;
DROP TABLE my_table;
ALTER TABLE new_table RENAME TO my_table;

Android 迁移:

public static final Migration MIGRATION_TEST = new Migration(1, 2) {
    @Override
    public void migrate(@NonNull SupportSQLiteDatabase database) {
        // Create new table
        database.execSQL("CREATE TABLE new_table (`_id` INTEGER PRIMARY KEY AUTOINCREMENT, `title` TEXT, `type` INTEGER NOT NULL)");
        // Copy some data
        database.execSQL("INSERT INTO new_table (title) SELECT title FROM old_table"); // constraint violation
        // Insert default value into the measures column
        database.execSQL("UPDATE new_table SET type = 1");
        // Delete old table
        database.execSQL("DROP TABLE old_table");
        // Rename new table
        database.execSQL("ALTER TABLE new_table RENAME TO my_table");
    }
};

显然我得到了NOT NULL约束失败:new_table.type错误:

android.database.sqlite.SQLiteConstraintException: NOT NULL constraint failed: new_table.type (code 1299)
Error Code : 1299 (SQLITE_CONSTRAINT_NOTNULL)
Caused By : Abort due to constraint violation.
(NOT NULL constraint failed: new_table.type (code 1299))

我可以通过更改新表的创建语句并为 type 列设置默认值来避免这种情况。

CREATE TABLE "new_table" 
 (`_id` INTEGER PRIMARY KEY AUTOINCREMENT,
  `title` TEXT,
  `type` INTEGER NOT NULL DEFAULT 1
 )

但我不想这样做,因为 Room 不支持开箱即用的默认值,也是为了避免将来在表中插入新值时出现错误。

在将数据插入新表时是否有任何解决方法可以避免此错误?

最佳答案

我认为以下方法可能有效:-

database.execSQL("INSERT INTO new_table (title,type) SELECT title, 1 FROM old_table");

也就是说,您现在要按照 SELECT 语句插入 2 列。 SELECT 返回 2 个值:old_table 中的标题和文字值 1。

那么您就不需要database.execSQL("UPDATE new_table SET type = 1")

关于android - 将数据复制到新表时 NOT NULL 约束失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54120189/

相关文章:

Android 媒体播放器仅播放一次声音

第一次初始化数据库的SQL脚本

multithreading - Peewee Sqlite 在内存数据库中的共享

java - SQLite 排序 COLLATE LOCALIZED 不起作用

Android apk 编译为 ART 运行时和 dalvik 运行时

android - setDataSource 失败 0x8000000

php - SQL语法只有两种类型的引号问题?

sql - 如何正确对 SQL 结果集进行分组?

java - Android 音频卡在底部扬声器上,无法在我的应用程序中使用耳机。应用程序也卡住

c++ - MonetDB 创建 100.000 列