GVKun编程网logo

将SQLite数据库从一个版本升级到另一个版本?

15

对于将SQLite数据库从一个版本升级到另一个版本?感兴趣的读者,本文将提供您所需要的所有信息,并且为您提供关于AndroidJava应用程序只能在一个版本上运行,而不能在下一个版本上运行、Andro

对于将SQLite数据库从一个版本升级到另一个版本?感兴趣的读者,本文将提供您所需要的所有信息,并且为您提供关于Android Java应用程序只能在一个版本上运行,而不能在下一个版本上运行、Android SQLite数据库版本升级原理解析、Android SQLite数据库版本升级的管理实现、android – 更新sqlite数据库版本?的宝贵知识。

本文目录一览:

将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 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
最佳答案
您正在使用哪个SDK版本来构建项目?如果它高于6,则必须确保您没有使用版本6之后添加的sdk部分.我要问的是,因为它暗示着您已将目标版本从8(2.2)降低了

如果这样做没有帮助,也许您可​​以发布完整的堆栈跟踪信息,这可能会提供其他线索.

Android SQLite数据库版本升级原理解析

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数据库版本升级的管理实现

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数据库版本?

android – 更新sqlite数据库版本?

我有一个数据库,我想添加一个列,我更改了静态数据库版本但是当我在我的设备上运行程序时,新列仍然没有,所以我猜我的onUpdate没有被调用,我不确定为什么.

这就是我创建数据库的方式

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,但仍然没有结果

解决方法

为了在Android中升级数据库,您应该将DATABASE_VERSION增加1,以便sqlOpenHelper知道它必须调用onUpgrade方法.

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数据库版本?的相关知识,请在本站搜索。

本文标签: