将数据复制到新 table 时 NOT NULL 约束失败
NOT NULL constraint failed while copying data to a new table
我将数据库从 SQLiteOpenHelper 迁移到 Room。
我有一个 table 想要更改,我们将其命名为 "my_table"
。
其简化的创建语句:
CREATE TABLE `my_table`
(`_id` INTEGER PRIMARY KEY AUTOINCREMENT,
`title` TEXT
)
在进行其他更改的升级过程中,我添加了新列 type INTEGER NOT NULL
(我还添加了外键并进行了其他重大更改,这就是创建新的 table 而不是更改的原因现有的):
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 constraint failed: 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))
我可以通过更改新 table 的创建语句并为 type
列设置默认值来避免它。
CREATE TABLE "new_table"
(`_id` INTEGER PRIMARY KEY AUTOINCREMENT,
`title` TEXT,
`type` INTEGER NOT NULL DEFAULT 1
)
但我不想这样做,因为 Room 不支持开箱即用的默认值,并且为了避免将来在 tables 中插入新值时出错。
在将数据插入新 table 时,是否有任何解决方法可以避免此错误?
我认为以下可能有效:-
database.execSQL("INSERT INTO new_table (title,type) SELECT title, 1 FROM old_table");
也就是说,您现在要按照 SELECT 语句插入 2 列。 SELECT returns 2 值来自 old_table 的标题和文字值 1.
即SELECT实际returns表达式result-column which aren't limited to just columns. An Expression can be literal value, result of functions, results of operations and other expr
的结果
根据
The list of expressions between the SELECT and FROM keywords is known
as the result expression list.
SQL As Understood By SQLite - SELECT - 3. Generation of the set of result rows.
那么你就不需要database.execSQL("UPDATE new_table SET type = 1")
。
我将数据库从 SQLiteOpenHelper 迁移到 Room。
我有一个 table 想要更改,我们将其命名为 "my_table"
。
其简化的创建语句:
CREATE TABLE `my_table`
(`_id` INTEGER PRIMARY KEY AUTOINCREMENT,
`title` TEXT
)
在进行其他更改的升级过程中,我添加了新列 type INTEGER NOT NULL
(我还添加了外键并进行了其他重大更改,这就是创建新的 table 而不是更改的原因现有的):
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 constraint failed: 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))
我可以通过更改新 table 的创建语句并为 type
列设置默认值来避免它。
CREATE TABLE "new_table"
(`_id` INTEGER PRIMARY KEY AUTOINCREMENT,
`title` TEXT,
`type` INTEGER NOT NULL DEFAULT 1
)
但我不想这样做,因为 Room 不支持开箱即用的默认值,并且为了避免将来在 tables 中插入新值时出错。
在将数据插入新 table 时,是否有任何解决方法可以避免此错误?
我认为以下可能有效:-
database.execSQL("INSERT INTO new_table (title,type) SELECT title, 1 FROM old_table");
也就是说,您现在要按照 SELECT 语句插入 2 列。 SELECT returns 2 值来自 old_table 的标题和文字值 1.
即SELECT实际returns表达式result-column which aren't limited to just columns. An Expression can be literal value, result of functions, results of operations and other expr
的结果
根据
The list of expressions between the SELECT and FROM keywords is known as the result expression list.
SQL As Understood By SQLite - SELECT - 3. Generation of the set of result rows.
那么你就不需要database.execSQL("UPDATE new_table SET type = 1")
。