Answers:
SQLiteOpenHelper onCreate()onUpgrade()当实际打开数据库时会调用和回调,例如通过调用getWritableDatabase()。创建数据库助手对象本身时,不会打开数据库。
SQLiteOpenHelper版本化数据库文件。版本号是int传递给构造函数的参数。在数据库文件中,版本号存储在中PRAGMA user_version。
onCreate()仅在数据库文件不存在且刚创建时运行。如果onCreate()成功返回(不引发异常),则假定使用请求的版本号创建数据库。这意味着,您不应该自己SQLException陷入onCreate()。
onUpgrade()仅在数据库文件存在但存储的版本号低于构造函数中的请求时调用。本onUpgrade()应更新表架构所需的版本。
在代码(onCreate())中更改表模式时,应确保数据库已更新。两种主要方法:
删除旧的数据库文件,以便onCreate()再次运行。在您可以控制安装版本并且数据丢失不是问题的开发时间,这通常是首选。删除数据库文件的一些方法:
卸载应用程序。使用应用程序管理器或adb uninstall your.package.name从外壳程序。
清除应用程序数据。使用应用程序管理器。
增加数据库版本,以便onUpgrade()调用它。随着需要更多代码,这会稍微复杂一些。
对于开发时架构升级而言,数据丢失不是问题,您可以使用execSQL("DROP TABLE IF EXISTS <tablename>")来删除现有表并调用onCreate()以重新创建数据库。
对于已发布的版本,应实施数据迁移,以onUpgrade()使用户不会丢失其数据。
onUpdate(),检查每个旧版本并进行适当的数据迁移。然后,当用户更新其应用程序(它们具有旧的db文件)时,onUpgrade将被触发,如果该用户是新安装的,则将onCreate()被触发。
根据Jaskey的要求,在此处进一步添加缺失点
数据库版本存储在SQLite数据库文件中。
catch是构造函数
SQLiteOpenHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version)
因此,当使用name(第二个参数)调用数据库帮助程序构造函数时,平台会检查数据库是否存在以及数据库是否存在,它将从数据库文件头获取版本信息并触发正确的回调
如较早的答案中已经解释的,如果名称不存在的数据库将触发onCreate。
下面的说明onUpgrade以示例说明情况。
假设您的应用程序的第一个版本具有DatabaseHelper(extended SQLiteOpenHelper),构造函数将version传递为as 1,然后为升级后的应用程序提供了新的源代码,其版本传递为2,然后在DatabaseHelper构建时自动触发平台,并onUpgrade通过查看文件已存在来触发该平台,但版本低于您通过的当前版本。
现在说你是刨去给应用程序与数据库版本的第三个版本3(DB版本会增加,只有当数据库架构修改)。在这种增量式升级中,您必须逐个增量地编写每个版本的升级逻辑,以便获得更好的可维护代码
下面的示例伪代码:
@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);
}
}
注意breakcase 1和中缺少的语句2。这就是我所说的增量升级。
假设旧版本是2,新版本是4,则逻辑将数据库从升级2到3,然后升级到4
如果旧版本3和新版本4,它只是运行升级的逻辑3来4
onCreate()
当我们第一次创建数据库(即数据库不存在)时,请onCreate()创建具有传入版本的数据库
SQLiteOpenHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version)
onCreate()方法是创建您定义的表并执行您编写的任何其他代码。但是,仅当应用程序的数据目录(/data/data/your.apps.classpath/databases)中缺少SQLite文件时,才会调用此方法。
如果您更改了代码并在模拟器中重新启动,则不会调用此方法。如果要onCreate()运行,则需要使用adb删除SQLite数据库文件。
onUpgrade()
SQLiteOpenHelper 应该调用超级构造函数。onUpgrade()仅当版本整数大于应用程序中运行的当前版本时,才会调用此方法。onUpgrade()调用该方法,则需要在代码中增加版本号。可能为时已晚,但我想分享我简短而甜美的答案。请检查“ 答案” 是否存在相同问题。肯定会对您有帮助。没有更深的规格。
如果您对创建表的语法有信心,那么在同一表中添加新列时可能会发生这种情况。
1)从设备上卸载并再次运行。
要么
2)设置->应用-> ClearData
要么
3)更改DATABASE_VERSION“ DatabaseHandler”类(如果添加了新列,它将自动升级)
public DatabaseHandler(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
要么
4)更改DATABASE_NAME您的“ DatabaseHandler”类(我遇到了同样的问题。但是通过更改我成功了DATABASE_NAME。)
扩展时要记住的要点 SQLiteOpenHelper
super(context, DBName, null, DBversion); -应该在构造函数的第一行调用onCreate和onUpgrade(如果需要)onCreate仅在getWritableDatabase()或getReadableDatabase()执行时才会调用。并且仅当DBName第一步中的指定不可用时才调用一次。您可以在onCreate方法上添加创建表查询DBversion并在onUpgrade表中进行查询,或者简单地卸载然后安装该应用程序即可。需要创建表时,首次调用onCreate。我们需要在编写用于创建表的脚本时覆盖此方法,该脚本由SQLiteDatabase执行。execSQL方法。在首次部署中执行后,将不会再调用此方法。
onUpgrade 在升级数据库版本时调用此方法。假设第一次部署的数据库版本为1,第二次部署的数据库结构发生了变化,例如在表中添加了额外的列。假设数据库版本现在为2。
您可以像创建数据库和表
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
找不到这样的表主要是因为您没有使用来打开SQLiteOpenHelper类,getwritabledata()并且在此之前还必须用databasename&version调用make构造函数。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);
}
}
您的数据库名称必须以.db结尾,查询字符串也必须带有终止符(;)。
在我的情况下,我从XML文件中获取<string-array>,其中存储<item>。在这些代码中,<item>我持有SQL字符串,并与一对一地应用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>
Sqliteopenhelper的方法具有create和upgrade方法,第一次创建任何表时都会使用create方法,并且每当表的列数更改时,都会每次调用一次upgrade方法。