提问人: 提问时间:2/19/2014 最后编辑:9 revs, 6 users 43%laalto 更新时间:2/2/2021 访问量:136886
SQLiteOpenHelper onCreate() / onUpgrade() 何时运行?
When does SQLiteOpenHelper onCreate() / onUpgrade() run?
问:
我已经在我的 但是 接收SQLiteOpenHelper
onCreate()
SQLiteException: no such table
或
SQLiteException: no such column
错误。为什么?
注意:
(这是每周数十个类似问题的合并摘要。试图在这里提供一个“规范的”社区维基问题/答案,以便所有这些问题都可以被引导到一个好的参考。
答:
SQLiteOpenHelper
onCreate
() 和 onUpgrade()
回调在实际打开数据库时调用,例如通过调用 getWritableDatabase()。
创建数据库帮助程序对象本身时,不会打开数据库。
SQLiteOpenHelper
对数据库文件进行版本控制。版本号是传递给构造函数的参数。在数据库文件中,版本号存储在 PRAGMA user_version
中。int
onCreate()
仅当数据库文件不存在且刚刚创建时才运行。如果返回成功(未引发异常),则假定使用请求的版本号创建数据库。言下之意,你不应该在自己身上抓住s。onCreate()
SQLException
onCreate()
onUpgrade()
仅当数据库文件存在但存储的版本号低于构造函数中请求的版本号时才调用。应将表架构更新为请求的版本。onUpgrade()
在代码 () 中更改表架构时,应确保数据库已更新。主要有两种方法:onCreate()
删除旧的数据库文件,以便再次运行该文件。在开发时,这通常是首选,因为您可以控制已安装的版本,并且数据丢失不是问题。删除数据库文件的一些方法:
onCreate()
卸载应用程序。使用应用程序管理器或从 shell 使用。
adb uninstall your.package.name
清除应用程序数据。使用应用程序管理器。
递增数据库版本,以便调用该版本。由于需要更多代码,这稍微复杂一些。
onUpgrade()
对于数据丢失不是问题的开发时架构升级,只需使用 in 删除现有表并调用以重新创建数据库。
execSQL("DROP TABLE IF EXISTS <tablename>")
onCreate()
对于已发布的版本,应实现数据迁移,以便用户不会丢失数据。
onUpgrade()
评论
onUpdate()
onUpgrade
onCreate()
根据 Jaskey 的要求,在此处进一步添加缺失的点
数据库版本存储在 SQLite
数据库文件中。
catch 是构造函数
SQLiteOpenHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version)
因此,当使用(第二个参数)调用数据库帮助程序构造函数时,平台会检查数据库是否存在,如果数据库存在,它会从数据库文件头获取版本信息并触发正确的回调name
正如在较早的答案中已经解释的那样,如果具有该名称的数据库不存在,它将触发 .onCreate
下面的解释用一个例子来解释情况。onUpgrade
比如说,您的第一个版本的应用程序具有(扩展)构造函数,将版本传递为,然后您提供了一个升级的应用程序,其中包含将版本传递为,然后在构造时自动触发,平台通过看到文件已经存在来触发,但版本低于您传递的当前版本。DatabaseHelper
SQLiteOpenHelper
1
2
DatabaseHelper
onUpgrade
现在,假设您计划提供第三个版本的应用程序,其 db 版本为 (db version 仅在要修改数据库架构时增加)。在此类增量升级中,必须以增量方式编写每个版本的升级逻辑,以获得更好的可维护代码3
下面的伪代码示例:
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
switch(oldVersion) {
case 1:
//upgrade logic from version 1 to 2
case 2:
//upgrade logic from version 2 to 3
case 3:
//upgrade logic from version 3 to 4
break;
default:
throw new IllegalStateException(
"onUpgrade() with unknown oldVersion " + oldVersion);
}
}
请注意 case 和 中缺少的语句。这就是我所说的增量升级。break
1
2
假设旧版本是,新版本是,那么逻辑会将数据库从 到 ,然后2
4
2
3
4
如果旧版本是,而新版本是 ,则只会运行 的升级逻辑3
4
3
4
评论
onCreate()
当我们第一次创建数据库时(即数据库不存在),使用传入的版本创建数据库
onCreate()
SQLiteOpenHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version)
onCreate()
方法创建您定义的表并执行您编写的任何其他代码。但是,仅当应用的数据目录 () 中缺少 SQLite 文件时,才会调用此方法。/data/data/your.apps.classpath/databases
如果已更改代码并在模拟器中重新启动,则不会调用此方法。如果要运行,则需要使用 adb 删除 SQLite 数据库文件。
onCreate()
onUpgrade()
SQLiteOpenHelper
应该调用超级构造函数。- 仅当版本整数大于应用中运行的当前版本时,才会调用该方法。
onUpgrade()
- 如果要调用该方法,则需要在代码中递增版本号。
onUpgrade()
评论
从模拟器或设备中卸载应用程序。再次运行应用。(当数据库已存在时,不执行 OnCreate())
扩展时要记住的要点SQLiteOpenHelper
super(context, DBName, null, DBversion);
- 这应该在构造函数的第一行调用- 覆盖和(如果需要)
onCreate
onUpgrade
onCreate
仅在执行 或 时调用。当第一步中指定的不可用时,这只会调用一次。您可以在方法上添加创建表查询getWritableDatabase()
getReadableDatabase()
DBName
onCreate
- 每当您想添加新表时,只需更改并在表中执行查询,或者只需卸载然后安装应用程序即可。
DBversion
onUpgrade
Sqliteopenhelper的方法有create和upgrade方法,create在首次创建任何表时使用,每次表的列数发生变化时都会调用upgrade方法。
评论
也许我为时已晚,但我想分享我简短而甜蜜的答案。 请检查“回答”以解决相同的问题。它肯定会对你有所帮助。没有更深层次的规格。
如果您对创建表的语法有信心,那么当您在同一表中添加新列时可能会发生这种情况,为此...
1)从您的设备中卸载并再次运行。
或
2) 设置 -> 应用程序 -> ClearData
或
3)更改“DatabaseHandler”类(如果您添加了新列,它将自动升级)DATABASE_VERSION
public DatabaseHandler(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
或
4)更改“DatabaseHandler”类(我遇到了同样的问题。但我通过改变成功了。DATABASE_NAME
DATABASE_NAME
评论
没有找到这样的表主要是当你没有打开类时,在此之前,你还必须用databasename和version调用make构造函数。
每当类中给定的版本号中有升级值时,都会调用。SQLiteOpenHelper
getwritabledata()
OnUpgrade
SQLiteOpenHelper
下面是代码片段(未找到此类列可能是因为列名称中的拼写):
public class database_db {
entry_data endb;
String file_name="Record.db";
SQLiteDatabase sq;
public database_db(Context c)
{
endb=new entry_data(c, file_name, null, 8);
}
public database_db open()
{
sq=endb.getWritableDatabase();
return this;
}
public Cursor getdata(String table)
{
return sq.query(table, null, null, null, null, null, null);
}
public long insert_data(String table,ContentValues value)
{
return sq.insert(table, null, value);
}
public void close()
{
sq.close();
}
public void delete(String table)
{
sq.delete(table,null,null);
}
}
class entry_data extends SQLiteOpenHelper
{
public entry_data(Context context, String name, SQLiteDatabase.CursorFactory factory,
int version) {
super(context, name, factory, version);
// TODO Auto-generated constructor stub
}
@Override
public void onCreate(SQLiteDatabase sqdb) {
// TODO Auto-generated method stub
sqdb.execSQL("CREATE TABLE IF NOT EXISTS 'YOUR_TABLE_NAME'(Column_1 text not null,Column_2 text not null);");
}
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
onCreate(db);
}
}
您可以创建数据库和表,例如
public class DbHelper extends SQLiteOpenHelper {
private static final String DBNAME = "testdatbase.db";
private static final int VERSION = 1;
public DbHelper(Context context) {
super(context, DBNAME, null, VERSION);
// TODO Auto-generated constructor stub
}
@Override
public void onCreate(SQLiteDatabase db) {
// TODO Auto-generated method stub
db.execSQL("create table BookDb(id integer primary key autoincrement,BookName text,Author text,IssuedOn text,DueDate text,Fine text,Totalfine text");
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("DROP TABLE IF EXISTS BookDb");
onCreate(db);
}
}
注意:如果要创建另一个表或添加列或没有此类表,只需递增 VERSION
数据库名称必须以 .db 结尾,查询字符串也必须具有终止符 (;)
如果您忘记提供“name”字符串作为构造函数的第二个参数,它会创建一个“内存中”数据库,当您关闭应用程序时,该数据库将被擦除。
onCreate 在需要创建表时首次调用。我们需要重写这个方法,其中我们编写了由 SQLiteDatabase 执行的表创建脚本。execSQL 方法。首次部署执行后,将不再调用此方法。
onUpgrade升级数据库版本时调用此方法。假设第一次部署,数据库版本为 1,在第二次部署中,数据库结构发生了变化,例如在表中添加了额外的列。假设数据库版本现在是 2。
在 DatabaseHandler/DatabaseManager 类中重新检查您的查询(无论您采用哪个类)
Sqlite 数据库覆盖两种方法
1)onCreate(): 此方法仅在应用程序首次启动时调用一次。所以它只叫了一次
2)onUpgrade() 当我们更改数据库版本时调用此方法,然后调用此方法。它用于更改表结构,例如在创建数据库模式后添加新列
就我而言,我从 XML 文件中获取项目,其中我存储了 s。在这些 s 中,我保存 SQL 字符串并用 .我犯了一个错误,忘记在引用之前添加并得到例外:<string-array>
<item>
<item>
databaseBuilder.addMigrations(migration)
\
android.database.sqlite.SQLiteException:没有这样的列: some_value(代码 1 SQLITE_ERROR):,编译时: INSERT INTO table_name(id, name) VALUES(1, some_value)
所以,这是一个正确的变体:
<item>
INSERT INTO table_name(id, name) VALUES(1, \"some_value\")
</item>
评论