我已经为我的应用创建了sqlite表,但现在我想在数据库中添加一个新表。
我将数据库版本更改为
private static final int DATABASE_VERSION = 2;
并添加字符串以创建表
private static final String DATABASE_CREATE_color =
"CREATE TABLE IF NOT EXISTS files(color text, incident_id text)";
onCreate
和onUpgrade
如下:
@Override
public void onCreate(SQLiteDatabase database) {
database.execSQL(DATABASE_CREATE_incident);
database.execSQL(DATABASE_CREATE_audio);
database.execSQL(DATABASE_CREATE_video);
database.execSQL(DATABASE_CREATE_image);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
//drop table and add new tables when version 2 released.
db.execSQL(DATABASE_CREATE_color);
}
但由于某种原因,没有创建新表。我做错了什么?
答案 0 :(得分:265)
<强> 1。关于onCreate()和onUpgrade()
只要新安装了应用程序,就会调用 onCreate(..)
。只要应用程序升级并启动并且数据库版本不同,就会调用onUpgrade
。
<强> 2。增加db版本
你需要一个像:
这样的构造函数MyOpenHelper(Context context) {
super(context, "dbname", null, 2); // 2 is the database version
}
重要提示:单独增加应用版本并不足以让onUpgrade
被调用!
第3。不要忘记您的新用户!
不要忘记添加
database.execSQL(DATABASE_CREATE_color);
也可以使用onCreate()方法,否则新安装的应用程序将缺少该表。
<强> 4。如何处理多个数据库随时间的变化
如果你有连续的应用升级,其中有几个有数据库升级,你想确保检查oldVersion
:
onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
switch(oldVersion) {
case 1:
db.execSQL(DATABASE_CREATE_color);
// we want both updates, so no break statement here...
case 2:
db.execSQL(DATABASE_CREATE_someothertable);
}
}
这样,当用户从版本1升级到版本3时,他们都会获得这两个更新。当用户从版本2升级到3时,他们只会获得版本3更新...毕竟,每次发布更新时,都不能指望100%的用户群升级。有时他们会跳过更新或12:)
<强> 5。在制定
时控制修订号最后......打电话
adb uninstall <yourpackagename>
完全卸载该应用。当你再次安装时,你可以保证点击onCreate
,这样你就不必在开发过程中不断将数据库版本增加到平流层......
答案 1 :(得分:9)
您的代码看起来是正确的。我的建议是数据库已经认为它已经升级了。如果在增加版本号后执行项目,但在添加execSQL
调用之前,测试设备/模拟器上的数据库可能已经相信它是在版本2中。
验证这一点的一种快速方法是将版本号更改为3 - 如果之后升级,您知道这只是因为您的设备认为它已经升级。
答案 2 :(得分:2)
您可以使用SQLiteOpenHelper的onUpgrade
方法。在onUpgrade方法中,您将oldVersion作为参数之一。
在onUpgrade
中使用switch
并在每个case
中使用版本号来跟踪当前版本的数据库。
最好从oldVersion
循环到newVersion
,一次将version
递增1,然后逐步升级数据库。当数据库版本1的人在很长一段时间后将应用程序升级到使用数据库版本7的版本并且应用程序因某些不兼容的更改而开始崩溃时,这非常有用。
然后,数据库中的更新将逐步完成,涵盖所有可能的情况,即合并为每个新版本完成的数据库更改,从而防止您的应用程序崩溃。
例如:
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
switch (oldVersion) {
case 1:
String sql = "ALTER TABLE " + TABLE_SECRET + " ADD COLUMN " + "name_of_column_to_be_added" + " INTEGER";
db.execSQL(sql);
break;
case 2:
String sql = "SOME_QUERY";
db.execSQL(sql);
break;
}
}
答案 3 :(得分:1)
@ jkschneider的答案是对的。然而,有一个更好的方法。
按照链接https://riggaroo.co.za/android-sqlite-database-use-onupgrade-correctly/
中的说明,在每个更新的sql文件中写入所需的更改from_1_to_2.sql
ALTER TABLE books ADD COLUMN book_rating INTEGER;
from_2_to_3.sql
ALTER TABLE books RENAME TO book_information;
from_3_to_4.sql
ALTER TABLE book_information ADD COLUMN calculated_pages_times_rating INTEGER;
UPDATE book_information SET calculated_pages_times_rating = (book_pages * book_rating) ;
这些.sql文件将根据数据库的版本在onUpgrade()方法中执行。
DatabaseHelper.java
public class DatabaseHelper extends SQLiteOpenHelper {
private static final int DATABASE_VERSION = 4;
private static final String DATABASE_NAME = "database.db";
private static final String TAG = DatabaseHelper.class.getName();
private static DatabaseHelper mInstance = null;
private final Context context;
private DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
this.context = context;
}
public static synchronized DatabaseHelper getInstance(Context ctx) {
if (mInstance == null) {
mInstance = new DatabaseHelper(ctx.getApplicationContext());
}
return mInstance;
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(BookEntry.SQL_CREATE_BOOK_ENTRY_TABLE);
// The rest of your create scripts go here.
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
Log.e(TAG, "Updating table from " + oldVersion + " to " + newVersion);
// You will not need to modify this unless you need to do some android specific things.
// When upgrading the database, all you need to do is add a file to the assets folder and name it:
// from_1_to_2.sql with the version that you are upgrading to as the last version.
try {
for (int i = oldVersion; i < newVersion; ++i) {
String migrationName = String.format("from_%d_to_%d.sql", i, (i + 1));
Log.d(TAG, "Looking for migration file: " + migrationName);
readAndExecuteSQLScript(db, context, migrationName);
}
} catch (Exception exception) {
Log.e(TAG, "Exception running upgrade script:", exception);
}
}
@Override
public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
private void readAndExecuteSQLScript(SQLiteDatabase db, Context ctx, String fileName) {
if (TextUtils.isEmpty(fileName)) {
Log.d(TAG, "SQL script file name is empty");
return;
}
Log.d(TAG, "Script found. Executing...");
AssetManager assetManager = ctx.getAssets();
BufferedReader reader = null;
try {
InputStream is = assetManager.open(fileName);
InputStreamReader isr = new InputStreamReader(is);
reader = new BufferedReader(isr);
executeSQLScript(db, reader);
} catch (IOException e) {
Log.e(TAG, "IOException:", e);
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
Log.e(TAG, "IOException:", e);
}
}
}
}
private void executeSQLScript(SQLiteDatabase db, BufferedReader reader) throws IOException {
String line;
StringBuilder statement = new StringBuilder();
while ((line = reader.readLine()) != null) {
statement.append(line);
statement.append("\n");
if (line.endsWith(";")) {
db.execSQL(statement.toString());
statement = new StringBuilder();
}
}
}
}
示例项目也在同一链接中提供:https://github.com/riggaroo/AndroidDatabaseUpgrades
答案 4 :(得分:1)
处理数据库版本是应用程序开发的重要组成部分。我假设您已经有类AppDbHelper扩展SQLiteOpenHelper
。扩展后,您需要实施onCreate
和onUpgrade
方法。
当onCreate
和onUpgrade
方法调用时
onCreate
被调用。onUpgrade
。 组织数据库版本
我在类方法中管理版本。创建接口Migration的实现。例如。对于第一个版本创建MigrationV1
类,第二个版本创建MigrationV1ToV2
(这些是我的命名约定)
public interface Migration {
void run(SQLiteDatabase db);//create tables, alter tables
}
示例迁移:
public class MigrationV1ToV2 implements Migration{
public void run(SQLiteDatabase db){
//create new tables
//alter existing tables(add column, add/remove constraint)
//etc.
}
}
onCreate
:由于在新安装应用程序时将调用onCreate
,因此我们还需要执行所有迁移(数据库版本更新)。所以onCreate
将如下所示:
public void onCreate(SQLiteDatabase db){
Migration mV1=new MigrationV1();
//put your first database schema in this class
mV1.run(db);
Migration mV1ToV2=new MigrationV1ToV2();
mV1ToV2.run(db);
//other migration if any
}
onUpgrade
:当已安装应用程序并将其更新为新的应用程序版本时,将调用此方法。如果应用程序包含任何数据库更改,则将所有数据库更改放入新的Migration类并增加数据库版本。
例如,假设用户已安装具有数据库版本1的应用程序,现在数据库版本已更新为2(所有架构更新保留在MigrationV1ToV2
中)。现在,当应用程序升级时,我们需要通过在MigrationV1ToV2
中应用数据库架构更改来升级数据库,如下所示:
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
if (oldVersion < 2) {
//means old version is 1
Migration migration = new MigrationV1ToV2();
migration.run(db);
}
if (oldVersion < 3) {
//means old version is 2
}
}
注意:数据库架构中的所有升级(在
中执行onUpgrade
中提及)都应在onCreate