对于将SQLite数据库从一个版本升级到另一个版本?感兴趣的读者,本文将提供您所需要的所有信息,并且为您提供关于AndroidJava应用程序只能在一个版本上运行,而不能在下一个版本上运行、Andro
对于将SQLite数据库从一个版本升级到另一个版本?感兴趣的读者,本文将提供您所需要的所有信息,并且为您提供关于Android Java应用程序只能在一个版本上运行,而不能在下一个版本上运行、Android SQLite数据库版本升级原理解析、Android SQLite数据库版本升级的管理实现、android – 更新sqlite数据库版本?的宝贵知识。
本文目录一览:- 将SQLite数据库从一个版本升级到另一个版本?
- Android Java应用程序只能在一个版本上运行,而不能在下一个版本上运行
- Android SQLite数据库版本升级原理解析
- Android SQLite数据库版本升级的管理实现
- android – 更新sqlite数据库版本?
将SQLite数据库从一个版本升级到另一个版本?
我从Logcat
说某个列(在我的SQLiteOpenHelper
子类中)不存在时得到一个错误。我以为可以通过更改DATABASE_CREATE
字符串来升级数据库。但是显然不是,那么如何将SQLite数据库从版本1逐步升级到版本2?
如果这个问题看起来“笨拙”,我深表歉意,但我仍在学习Android。
@ Pentium10这是我在onUpgrade中所做的:
private static final int DATABASE_VERSION = 1;....switch (upgradeVersion) {case 1: db.execSQL("ALTER TABLE task ADD body TEXT"); upgradeVersion = 2; break;}...
答案1
小编典典好的,在遇到更大的问题之前,您应该知道SQLite受到ALTER
TABLE命令的限制,它仅允许add
并且rename
不允许通过重新创建表进行删除/删除操作。
您应该始终手头有新的表创建查询,并将其用于升级和传输任何现有数据。注意:onUpgrade方法为sqlite辅助对象运行一个,并且您需要处理其中的所有表。
那么建议在Upgrade上进行以下操作:
- beginTransaction
- 使用运行表创建
if not exists
(我们正在进行升级,因此该表可能尚不存在,更改和删除将失败) - 将现有列放在列表中
List<String> columns = DBUtils.GetColumns(db, TableName);
- 备用表(
ALTER table " + TableName + " RENAME TO ''temp_" + TableName
) - 创建新表(最新的表创建模式)
- 获取与新列的交集,这次列取自升级表(
columns.retainAll(DBUtils.GetColumns(db, TableName));
) - 恢复数据(
String cols = StringUtils.join(columns, ","); db.execSQL(String.format( "INSERT INTO %s (%s) SELECT %s from temp_%s", TableName, cols, cols, TableName));
) - 删除备份表(
DROP table ''temp_" + TableName
) - setTransactionSuccessful
。
public static List<String> GetColumns(SQLiteDatabase db, String tableName) { List<String> ar = null; Cursor c = null; try { c = db.rawQuery("select * from " + tableName + " limit 1", null); if (c != null) { ar = new ArrayList<String>(Arrays.asList(c.getColumnNames())); } } catch (Exception e) { Log.v(tableName, e.getMessage(), e); e.printStackTrace(); } finally { if (c != null) c.close(); } return ar;}public static String join(List<String> list, String delim) { StringBuilder buf = new StringBuilder(); int num = list.size(); for (int i = 0; i < num; i++) { if (i != 0) buf.append(delim); buf.append((String) list.get(i)); } return buf.toString();}
Android Java应用程序只能在一个版本上运行,而不能在下一个版本上运行
我对android很陌生,实际上是昨天才开始的.我设法获得带有标签的应用程序设置.它在2.2虚拟avd上运行良好(我认为这被称为).但是我的HTC版本是2.0.1
我在下面发布代码片段以及调试信息.
Logcat显示以下错误
08-02 09:56:05.946: WARN/dalvikvm(414): threadid=3: thread exiting with uncaught exception (group=0x4001b188)
08-02 09:56:05.956: ERROR/AndroidRuntime(414): Uncaught handler: thread main exiting due to uncaught exception
08-02 09:56:06.196: ERROR/AndroidRuntime(414): java.lang.RuntimeException: Unable to start activity ComponentInfo{org.hyperActiveSolutions/org.hyperActiveSolutions.Organizer}: java.lang.NullPointerException
08-02 09:56:06.196: ERROR/AndroidRuntime(414): at android.app.ActivityThread.performlaunchActivity(ActivityThread.java:2481)
08-02 09:56:06.196: ERROR/AndroidRuntime(414): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2497)
还有更多,但我认为这是相关的,其余只是长堆栈跟踪.
我的android清单文件看起来像这样
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.hyperActiveSolutions"
android:versionCode="1"
android:versionName="1.0">
<application android:icon="@drawable/icon" android:label="@string/app_name">
<activity android:label="@string/app_name"
android:theme="@android:style/Theme.NoTitleBar" android:name="Organizer">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name="Home" ></activity>
<activity android:name="Account"></activity>
<activity android:name="Agenda" ></activity>
<activity android:name="Lists" ></activity>
</application>
<uses-sdk android:minSdkVersion="6" android:targetSdkVersion="6"></uses-sdk>
</manifest>
如您所见,最低sdk和目标已设置为我手机的版本.这是我入门课程的开始.在此代码段结束的下方,以与“主页”完全相同的方式添加了其他3个选项卡.
public class Organizer extends tabactivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.setContentView(R.layout.main);
final TabHost tabHost = getTabHost(); // The activity TabHost
// Create an Intent to launch an Activity for the tab (to be reused)
// Initialize a TabSpec for each tab and add it to the TabHost
tabHost.addTab(tabHost.newTabSpec("home").setIndicator("Home",getResources().getDrawable(R.drawable.home)).setContent(new Intent().setClass(this,Home.class)));
我所有的资源都存在,包括每个选项卡实例化的类.
我唯一想到的可能与之相关的是布局的main.xml.
在教程之一中,它是从android dev网站复制的.
<?xml version="1.0" encoding="utf-8"?>
<TabHost xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@android:id/tabhost"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TabWidget
android:id="@android:id/tabs"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
<FrameLayout
android:id="@android:id/tabcontent"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
</LinearLayout>
</TabHost>
正如我所说的,它在2.2版上可以正常运行,但在2.0.1版上死了,并且屏幕上显示的消息只是“ Organizer意外终止”.
因此,任何人都可以发现我拥有的所有内容,使其与2.0.1 SDK不兼容.
提前致谢
全栈跟踪
08-02 11:47:54.006: WARN/dalvikvm(2588): threadid=3: thread exiting with uncaught exception (group=0x4001b188)
08-02 11:47:54.016: ERROR/AndroidRuntime(2588): Uncaught handler: thread main exiting due to uncaught exception
08-02 11:47:54.256: ERROR/AndroidRuntime(2588): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.organizer/com.organizer.Organizer}: java.lang.NullPointerException
08-02 11:47:54.256: ERROR/AndroidRuntime(2588): at android.app.ActivityThread.performlaunchActivity(ActivityThread.java:2481)
08-02 11:47:54.256: ERROR/AndroidRuntime(2588): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2497)
08-02 11:47:54.256: ERROR/AndroidRuntime(2588): at android.app.ActivityThread.access$2200(ActivityThread.java:119)
08-02 11:47:54.256: ERROR/AndroidRuntime(2588): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1848)
08-02 11:47:54.256: ERROR/AndroidRuntime(2588): at android.os.Handler.dispatchMessage(Handler.java:99)
08-02 11:47:54.256: ERROR/AndroidRuntime(2588): at android.os.Looper.loop(Looper.java:123)
08-02 11:47:54.256: ERROR/AndroidRuntime(2588): at android.app.ActivityThread.main(ActivityThread.java:4338)
08-02 11:47:54.256: ERROR/AndroidRuntime(2588): at java.lang.reflect.Method.invokeNative(Native Method)
08-02 11:47:54.256: ERROR/AndroidRuntime(2588): at java.lang.reflect.Method.invoke(Method.java:521)
08-02 11:47:54.256: ERROR/AndroidRuntime(2588): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:860)
08-02 11:47:54.256: ERROR/AndroidRuntime(2588): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618)
08-02 11:47:54.256: ERROR/AndroidRuntime(2588): at dalvik.system.NativeStart.main(Native Method)
08-02 11:47:54.256: ERROR/AndroidRuntime(2588): Caused by: java.lang.NullPointerException
08-02 11:47:54.256: ERROR/AndroidRuntime(2588): at android.widget.TabWidget.onFocusChange(TabWidget.java:351)
08-02 11:47:54.256: ERROR/AndroidRuntime(2588): at android.view.View.onFocusChanged(View.java:2622)
08-02 11:47:54.256: ERROR/AndroidRuntime(2588): at android.view.View.handleFocusGainInternal(View.java:2445)
08-02 11:47:54.256: ERROR/AndroidRuntime(2588): at android.view.ViewGroup.handleFocusGainInternal(ViewGroup.java:403)
08-02 11:47:54.256: ERROR/AndroidRuntime(2588): at android.view.View.requestFocus(View.java:3562)
08-02 11:47:54.256: ERROR/AndroidRuntime(2588): at android.view.ViewGroup.requestFocus(ViewGroup.java:975)
08-02 11:47:54.256: ERROR/AndroidRuntime(2588): at android.view.ViewGroup.onRequestFocusInDescendants(ViewGroup.java:1020)
08-02 11:47:54.256: ERROR/AndroidRuntime(2588): at android.view.ViewGroup.requestFocus(ViewGroup.java:976)
08-02 11:47:54.256: ERROR/AndroidRuntime(2588): at android.view.ViewGroup.onRequestFocusInDescendants(ViewGroup.java:1020)
08-02 11:47:54.256: ERROR/AndroidRuntime(2588): at android.view.ViewGroup.requestFocus(ViewGroup.java:979)
08-02 11:47:54.256: ERROR/AndroidRuntime(2588): at android.view.ViewGroup.onRequestFocusInDescendants(ViewGroup.java:1020)
08-02 11:47:54.256: ERROR/AndroidRuntime(2588): at android.view.ViewGroup.requestFocus(ViewGroup.java:976)
08-02 11:47:54.256: ERROR/AndroidRuntime(2588): at android.view.ViewGroup.onRequestFocusInDescendants(ViewGroup.java:1020)
08-02 11:47:54.256: ERROR/AndroidRuntime(2588): at android.view.ViewGroup.requestFocus(ViewGroup.java:979)
08-02 11:47:54.256: ERROR/AndroidRuntime(2588): at android.view.View.requestFocus(View.java:3513)
08-02 11:47:54.256: ERROR/AndroidRuntime(2588): at android.view.View.requestFocus(View.java:3491)
08-02 11:47:54.256: ERROR/AndroidRuntime(2588): at android.widget.TabHost.setCurrentTab(TabHost.java:334)
08-02 11:47:54.256: ERROR/AndroidRuntime(2588): at android.widget.TabHost.addTab(TabHost.java:213)
08-02 11:47:54.256: ERROR/AndroidRuntime(2588): at com.organizer.Organizer.onCreate(Organizer.java:25)
08-02 11:47:54.256: ERROR/AndroidRuntime(2588): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
08-02 11:47:54.256: ERROR/AndroidRuntime(2588): at android.app.ActivityThread.performlaunchActivity(ActivityThread.java:2444)
08-02 11:47:54.256: ERROR/AndroidRuntime(2588): ... 11 more
08-02 11:47:54.476: INFO/Process(62): Sending signal. PID: 2588 SIG: 3
08-02 11:47:54.476: INFO/dalvikvm(2588): threadid=7: reacting to signal 3
08-02 11:47:54.476: ERROR/dalvikvm(2588): Unable to open stack trace file '/data/anr/traces.txt': Permission denied
08-02 11:48:01.446: INFO/dalvikvm(2588): Debugger has detached; object registry had 306 entries
08-02 11:48:02.466: DEBUG/ddm-heap(2588): Got feature list request
如果这样做没有帮助,也许您可以发布完整的堆栈跟踪信息,这可能会提供其他线索.
Android SQLite数据库版本升级原理解析
Android使用sqlite数据库保存数据,那数据库版本升级是怎么回事呢,这里说一下。
一、软件v1.0
安装v1.0,假设v1.0版本只有一个account表,这时走继承sqliteOpenHelper的onCreate,不走onUpgrade。
1、v1.0(直接安装v1.0)
二、软件v2.0
有2种安装软件情况:
1、v1.0 --> v2.0 不走onCreate,走onUpgrade
2、v2.0(直接安装v2.0) 走onCreate,不走onUpgrade
v1.0版本只有一个account表,软件版本升级到v2.0了,但是v2.0数据库需要新增一个member表,那怎么办呢?这里有2种情况了:一种是安装了v1.0升级到v2.0,这时不会走继承sqliteOpenHelper的onCreate,而是直接走onUpgrade,这时就要在onUpgrade添加member表的代码了,在onCreate加了也没用,因为这种情况都不走onCreate。。另一种情况就是用户从来没有安装过这个软件,直接安装v2.0,这时走继承sqliteOpenHelper的onCreate,不走onUpgrade,所以要在onCreate添加member表的代码。这怎么办呢?这就要合理升级数据库版本了。
三、软件v3.0
假设v3.0又新增一个news表,这里有三种情况:
1、v1.0 --> v3.0 不走onCreate,走onUpgrade
2、v2.0 --> v3.0 不走onCreate,走onUpgrade
3、v3.0(直接安装v3.0) 走onCreate,不走onUpgrade
那数据库添加表语句在那里写呢?数据库有一个版本号用DATABASE_VERSION表示
其实想一下,就知道不是onCreate写就是onUpgrade写,就是要兼容各种情况下安装app,都能把数据库表添加进去就好了。这里很巧妙:
1、v1.0 DATABASE_VERSION=1000 onCreate --添加-- account
2、v2.0 DATABASE_VERSION=1001 onCreate --添加-- account (v1.0代码不变) onUpgrade(DATABASE_VERSION>1000)
onUpgrade --添加-- member
3、v3.0 DATABASE_VERSION=1002 onCreate --添加-- account (v1.0代码不变) onUpgrade(DATABASE_VERSION>1001)
onUpgrade --添加-- member (v2.0代码不变)
onUpgrade --添加-- news
这样就可以解决问题了,第一版本的都在onCreate,其他版本新增的在onUpgrade,而且在onCreate执行onUpgrade。做判断是否执行onUpgrade该怎么判断呢,所以有了数据库版本的概念了,DATABASE_VERSION保存当前的数据库版本,只要当前的数据库版本比已经安装的数据库版本大时,就进入onUpgrade,这时还会把上一个数据库版本号(oldVersion)跟安装的数据库版本号(newVersion)做比较,不同的DATABASE_VERSION添加自己所需要的表(跨版本升级数据库)。
下面做一个简单的实例:
(1)、V1.0 : DATABASE_VERSION = 1000 添加一个favorite表
public class DBHelper extends sqliteOpenHelper { private static final String DATABASE_NAME = "mall.db"; private static final int DATABASE_VERSION = 1000; private static DBHelper instance = null; public DBHelper(Context context) { super(context,DATABASE_NAME,null,DATABASE_VERSION); } public synchronized static DBHelper getInstance(Context context) { if (instance == null) { instance = new DBHelper(context); } return instance; } @Override public void onCreate(sqliteDatabase db) { db.execsql(sql.CREATE_TABLE_FAVORITE); // 若不是第一个版本安装,直接执行数据库升级 // 请不要修改FirsT_DATABASE_VERSION的值,其为第一个数据库版本大小 final int FirsT_DATABASE_VERSION = 1000; onUpgrade(db,FirsT_DATABASE_VERSION,DATABASE_VERSION); } @Override public void onUpgrade(sqliteDatabase db,int oldVersion,int newVersion) { // 使用for实现跨版本升级数据库 for (int i = oldVersion; i < newVersion; i++) { switch (i) { default: break; } } } }
其中sql.java是建表语句
public class sql { public static final String T_FAVORITE = "favorite"; public static final String CREATE_TABLE_FAVORITE = "CREATE TABLE IF NOT EXISTS " + T_FAVORITE + "(" + "id VARCHAR PRIMARY KEY," + "title VARCHAR," + "url VARCHAR," + "createDate VARCHAR " + ")"; }
(2)、V2.0 : DATABASE_VERSION = 1001 在favorite表添加1个deleted字段
public class DBHelper extends sqliteOpenHelper { private static final String DATABASE_NAME = "mall.db"; private static final int DATABASE_VERSION = 1001; private static DBHelper instance = null; public DBHelper(Context context) { super(context,int newVersion) { // 使用for实现跨版本升级数据库 for (int i = oldVersion; i < newVersion; i++) { switch (i) { case 1000: upgradetoVersion1001(db); break; default: break; } } } private void upgradetoVersion1001(sqliteDatabase db){ // favorite表新增1个字段 String sql1 = "ALTER TABLE "+sql.T_FAVORITE+" ADD COLUMN deleted VARCHAR"; db.execsql(sql1); } }
(3)、V3.0 : DATABASE_VERSION = 1002 在favorite表添加message和type字段
public class DBHelper extends sqliteOpenHelper { private static final String DATABASE_NAME = "mall.db"; private static final int DATABASE_VERSION = 1002; private static DBHelper instance = null; public DBHelper(Context context) { super(context,int newVersion) { // 使用for实现跨版本升级数据库 for (int i = oldVersion; i < newVersion; i++) { switch (i) { case 1000: upgradetoVersion1001(db); break; case 1001: upgradetoVersion1002(db); break; default: break; } } } private void upgradetoVersion1001(sqliteDatabase db){ // favorite表新增1个字段 String sql1 = "ALTER TABLE "+sql.T_FAVORITE+" ADD COLUMN deleted VARCHAR"; db.execsql(sql1); } private void upgradetoVersion1002(sqliteDatabase db){ // favorite表新增2个字段,添加新字段只能一个字段一个字段加,sqlite有限制不予许一条语句加多个字段 String sql1 = "ALTER TABLE "+sql.T_FAVORITE+" ADD COLUMN message VARCHAR"; String sql2 = "ALTER TABLE "+sql.T_FAVORITE+" ADD COLUMN type VARCHAR"; db.execsql(sql1); db.execsql(sql2); } }
就是这样,无论v1.0升级到v3.0,或者v2.0升级到3.0,还是v3.0直接安装,安装后的v3.0数据库结构都是一样的,理解透彻就是好啊,刚做sqlite数据库的肯定会遇到这些问题,所以在这里详细地写了一下,不过还是要注意一下,就是onUpgrade升级时候一定要写对,测试好,不然安装后的数据库都有问题就麻烦了。
本人原创,转发请附上链接:http://www.cnblogs.com/liqw/p/4264925.html
Android SQLite数据库版本升级的管理实现
Android sqlite数据库版本升级的管理实现
我们知道在sqliteOpenHelper的构造方法:
super(Context context,String name,sqliteDatabase.CursorFactory factory,int version)
中最后一个参数表示数据库的版本号.当新的版本号大于当前的version时会调用方法:
onUpgrade(sqliteDatabase db,int oldVersion,int newVersion)
所以我们的重点是在该方法中实现sqlite数据库版本升级的管理
当我们项目刚开始的时候第一版sqliteOpenHelper是这样写的:
package cc.database; import android.content.Context; import android.database.sqlite.sqliteDatabase; import android.database.sqlite.sqliteDatabase.CursorFactory; import android.database.sqlite.sqliteOpenHelper; /** * Demo描述: * sqlite数据库版本升级的管理实现 * * 参考资料: * http://blog.csdn.net/guolin_blog * Thank you very much */ public class DataBaSEOpenHelper extends sqliteOpenHelper { private final static String DATABASE_NAME="test.db"; private static DataBaSEOpenHelper mDataBaSEOpenHelper; public static final String CREATE_PERSON= "create table person(personid integer primary key autoincrement,name varchar(20),phone VARCHAR(12))"; public DataBaSEOpenHelper(Context context,CursorFactory factory,int version) { super(context,name,factory,version); } //注意: //将DataBaSEOpenHelper写成单例的. //否则当在一个for循环中频繁调用openHelper.getWritableDatabase()时 //会报错,提示数据库没有执行关闭操作 static synchronized DataBaSEOpenHelper getDBInstance(Context context) { if (mDataBaSEOpenHelper == null) { mDataBaSEOpenHelper = new DataBaSEOpenHelper(context,DATABASE_NAME,null,1); } return mDataBaSEOpenHelper; } @Override public void onCreate(sqliteDatabase db) { db.execsql(CREATE_PERSON); } @Override public void onUpgrade(sqliteDatabase db,int newVersion) { } }
在几天之后根据项目需求,需要添加一张student表,于是DataBaSEOpenHelper就出现了第二版:
package cc.database; import android.content.Context; import android.database.sqlite.sqliteDatabase; import android.database.sqlite.sqliteDatabase.CursorFactory; import android.database.sqlite.sqliteOpenHelper; public class DataBaSEOpenHelper extends sqliteOpenHelper { private final static String DATABASE_NAME="test.db"; private static DataBaSEOpenHelper mDataBaSEOpenHelper; public static final String CREATE_PERSON= "create table person(personid integer primary key autoincrement,phone VARCHAR(12))"; public static final String CREATE_STUDENT= "create table student(studentid integer primary key autoincrement,提示数据库没有执行关闭操作 static synchronized DataBaSEOpenHelper getDBInstance(Context context) { if (mDataBaSEOpenHelper == null) { //改动1 mDataBaSEOpenHelper = new DataBaSEOpenHelper(context,2); } return mDataBaSEOpenHelper; } @Override public void onCreate(sqliteDatabase db) { db.execsql(CREATE_PERSON); //改动2 db.execsql(CREATE_STUDENT); } @Override public void onUpgrade(sqliteDatabase db,int newVersion) { //改动3 switch (oldVersion) { case 1: db.execsql(CREATE_STUDENT); default: } } }
较版本一在版本二中有三处修改的地方:
1 版本号变成了2
2 在onCreate()方法中添加了代码db.execsql(CREATE_STUDENT);创建student表
因为有的用户根本就没有第一版本的APP,直接从市场下载了第二版本的App。所以当然会执行onCreate()而不会执行onUpgrade()
3 在onUpgrade()做了处理:当oldVersion为1时调用db.execsql(CREATE_STUDENT);创建student表
因为有的用户手机上本来就有第一版本的APP,所以在App升级到第二版本时会执行onUpgrade(),不会执行onCreate()
通过这样的处理使得不同的情况下使用第二版APP时都会生成student表
又过了一个月,根据项目变更,需要给person表添加一个字段genderid,于是DataBaSEOpenHelper就出现了第三版:
package cc.database; import android.content.Context; import android.database.sqlite.sqliteDatabase; import android.database.sqlite.sqliteDatabase.CursorFactory; import android.database.sqlite.sqliteOpenHelper; public class DataBaSEOpenHelper extends sqliteOpenHelper { private final static String DATABASE_NAME="test.db"; private static DataBaSEOpenHelper mDataBaSEOpenHelper; //改动1 public static final String CREATE_PERSON= "create table person(personid integer primary key autoincrement,phone VARCHAR(12)),genderid integer)"; public static final String ALTER_PERSON="alter table person add column genderid integer"; public static final String CREATE_STUDENT= "create table student(studentid integer primary key autoincrement,提示数据库没有执行关闭操作 static synchronized DataBaSEOpenHelper getDBInstance(Context context) { if (mDataBaSEOpenHelper == null) { //改动2 mDataBaSEOpenHelper = new DataBaSEOpenHelper(context,3); } return mDataBaSEOpenHelper; } @Override public void onCreate(sqliteDatabase db) { db.execsql(CREATE_PERSON); db.execsql(CREATE_STUDENT); } @Override public void onUpgrade(sqliteDatabase db,int newVersion) { switch (oldVersion) { case 1: db.execsql(CREATE_STUDENT); //改动3 case 2: db.execsql(ALTER_PERSON); default: } } }
较版本二在版本三中有三处修改的地方:
1 改变了CREATE_PERSON语句,在改语句中增加了一个字段genderid
和前面的描述类似,有的用户第一次安装该APP时就直接下载了第三版
2 修改版本号为3
应对了用户从第一版本或者第二版本升级到第三版本的情况(见下分析)
3 在onUpgrade()方法中)做了处理:当oldVersion为2时调用 db.execsql(ALTER_PERSON);修改person表,增加genderid字段
应对了用户从第二版本升级到第三版本的情况(见下分析)
注意一个问题:为什么这里的switch语句在每个case中没有break???
这是为了保证跨版本升级的时候每次数据库的升级都会执行到。
比如从第二版升级到第三版本,那么case 2会被执行。
比如从第一版直接升级到第三版本,那么case 1肯定会被调用,由于没有break所以会穿透switch语句又执行case 2语句继续升级,从而保证了数据的所有版本中的升级都会被执行到。
如有疑问请留言或者到本站社区交流讨论,感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!
android – 更新sqlite数据库版本?
这就是我创建数据库的方式
private static class DatabaseHelper extends sqliteOpenHelper { DatabaseHelper(Context context) { super(context,DATABASE_NAME,null,DATABASE_VERSION); } @Override public void onCreate(sqliteDatabase db) { createTables(db); } @Override public void onUpgrade(sqliteDatabase db,int oldVersion,int newVersion) { Log.w("CalendarDB","Upgrading database from version " + oldVersion + " to " + newVersion + ",which will destroy all old data"); db.execsql("DROP TABLE IF EXISTS Events_Table"); onCreate(db); } private void createTables(sqliteDatabase db){ db.execsql("CREATE TABLE " + EVENTS_TABLE + "(" + ID + " integer primary key autoincrement," + EVENT + " TEXT," + LOCATION + " TEXT," + DESCRIPTION + " TEXT," + DATE + " TEXT," + START + " LONG," + END + " TEXT," + REAL_START_TIME + " TEXT," + REAL_END_TIME + " TEXT," + COLOR + " TEXT," + BLINK + " TEXT," + VIBRATE + " TEXT," + RING_TONE_PATH + " TEXT," + ICON + " TEXT," + REMINDERS + " TEXT," + START_WITH_REMINDER + " TEXT," + CALENDAR_ID + " TEXT," + EVENT_ID + " TEXT);"); } }
还有什么我需要做的才能让onUpdate被调用吗?我试过跟随this answer,但仍然没有结果
解决方法
Rembember
这仅在您调用getWritableDatabase()时有效,否则将无法升级.如果更改版本并调用getReadableDatabase,它将显示异常
throw new sqliteException("Can't upgrade read-only database from version " + db.getVersion() + " to " + mNewVersion + ": " + path);
但为什么?
你看到当你拨打getWritableDatabase代码检查时,版本是相同的:
if (version != mNewVersion) { db.beginTransaction(); try { if (version == 0) { onCreate(db); } else { if (version > mNewVersion) { onDowngrade(db,version,mNewVersion); } else { onUpgrade(db,mNewVersion); } } db.setVersion(mNewVersion); db.setTransactionSuccessful(); } finally { db.endTransaction(); } }
更新
事实证明它应该与getReadableDatabase()一起使用,因为在代码中你总是得到一个WrittableDatabase.所以它应该适用于这两种方法,这里是getReadableDatabase()的文档:
Create and/or open a database. This will be the same object returned by getWritableDatabase() unless some problem,such as a full disk,requires the database to be opened read-only. In that case,a read-only database object will be returned. If the problem is fixed,a future call to getWritableDatabase() may succeed,in which case the read-only database object will be closed and the read/write object will be returned in the future.
今天关于将SQLite数据库从一个版本升级到另一个版本?的讲解已经结束,谢谢您的阅读,如果想了解更多关于Android Java应用程序只能在一个版本上运行,而不能在下一个版本上运行、Android SQLite数据库版本升级原理解析、Android SQLite数据库版本升级的管理实现、android – 更新sqlite数据库版本?的相关知识,请在本站搜索。
本文标签: