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);
}
}
注意break
case 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方法。