Android如何使用SQLiteOpenHelper在已经存在的数据库中插入一个字段

2018-02-04 23:56:45

Andoird的SQLiteOpenHelper类中有一个onUpgrade方法。帮助文档中只是说当数据库升级时该方法被触发。经过实践,解决了我一连串的疑问:

1. 帮助文档里说的“数据库升级”是指什么?


你开发了一个程序,当前是1.0版本。该程序用到了数据库。到1.1版本时,你在数据库的某个表中增加了一个字段。那么软件1.0版本用的数据库在软件1.1版本就要被升级了。


2. 数据库升级应该注意什么?


软件的1.0版本升级到1.1版本时,老的数据不能丢。那么在1.1版本的程序中就要有地方能够检测出来新的软件版本与老的数据库不兼容,并且能够有办法把1.0软件的数据库升级到1.1软件能够使用的数据库。换句话说,要在1.0软件的数据库的那个表中增加那个字段,并赋予这个字段默认值。


3. 程序如何知道数据库需要升级?


SQLiteOpenHelper类的构造函数有一个参数是int version,它的意思就是指数据库版本号。比如在软件1.0版本中,我们使用SQLiteOpenHelper访问数据库时,该参数为1,那么数据库版本号1就会写在我们的数据库中。


到了1.1版本,我们的数据库需要发生变化,那么我们1.1版本的程序中就要使用一个大于1的整数来构造SQLiteOpenHelper类,用于访问新的数据库,比如2。


当我们的1.1新程序读取1.0版本的老数据库时,就发现老数据库里存储的数据库版本是1,而我们新程序访问它时填的版本号为2,系统就知道数据库需要升级。


4. 何时触发数据库升级?如何升级?


当系统在构造SQLiteOpenHelper类的对象时,如果发现版本号不一样,就会自动调用onUpgrade函数,让你在这里对数据库进行升级。根据上述场景,在这个函数中把老版本数据库的相应表中增加字段,并给每条记录增加默认值即可。


新版本号和老版本号都会作为onUpgrade函数的参数传进来,便于开发者知道数据库应该从哪个版本升级到哪个版本。


升级完成后,数据库会自动存储最新的版本号为当前数据库版本号。



做Android应用,不可避免的会与SQLite打交道。随着应用的不断升级,原有的数据库结构可能已经不再适应新的功能,这时候,就需要对SQLite数据库的结构进行升级了。 SQLite提供了ALTER TABLE命令,允许用户重命名或添加新的字段到已有表中,但是不能从表中删除字段。

并且只能在表的末尾添加字段,比如,为 Subscription添加两个字段:

1 ALTER TABLE Subscription ADD COLUMN Activation BLOB;

2 ALTER TABLE Subscription ADD COLUMN Key BLOB;



  另外,如果遇到复杂的修改操作,比如在修改的同时,需要进行数据的转移,那么可以采取在一个事务中执行如下语句来实现修改表的需求。

  1. 将表名改为临时表

         ALTER TABLE Subscription RENAME TO __temp__Subscription;


  2. 创建新表

        CREATE TABLE Subscription (OrderId VARCHAR(32) PRIMARY KEY ,UserName VARCHAR(32) NOT NULL ,ProductId VARCHAR(16) NOT NULL);

  

      3. 导入数据  

         INSERT INTO Subscription SELECT OrderId, “”, ProductId FROM __temp__Subscription;

  或者  

        INSERT INTO Subscription() SELECT OrderId, “”, ProductId FROM __temp__Subscription;

  * 注意 双引号”” 是用来补充原来不存在的数据的

  

      4. 删除临时表  

        DROP TABLE __temp__Subscription;


  通过以上四个步骤,就可以完成旧数据库结构向新数据库结构的迁移,并且其中还可以保证数据不会应为升级而流失。

  当然,如果遇到减少字段的情况,也可以通过创建临时表的方式来实现。


Android应用程序更新的时候如果数据库修改了字段需要更新数据库,并且保留原来的数据库数据:

这是原有的数据库表

CREATE_BOOK = "create table book(bookId integer primarykey,bookName text);";

然后我们增加一个字段:

CREATE_BOOK = "create table book(bookId integer primarykey,bookName text,bookContent text);";

首先我们需要把原来的数据库表重命名一下

CREATE_TEMP_BOOK = "alter table book rename to _temp_book";

然后把备份表中的数据copy到新创建的数据库表中

INSERT_DATA = "insert into book select *,' ' from _temp_book";(注意' '是为新加的字段插入默认值的必须加上,否则就会出错)。

然后我们把备份表干掉就行啦。

DROP_BOOK = "drop table _temp_book";

然后把数据库的版本后修改一下,再次创建数据库操作对象的时候就会自动更新(注:更新的时候第一个创建的操作数据的对象必须是可写的,也就是通过这个方法getWritableDatabase()获取的数据库操作对象)

然后在onUpgrade()方法中执行上述sql语句就OK了

public class DBservice extends SQLiteOpenHelper{

    private String CREATE_BOOK = "create table book(bookId integer primarykey,bookName text);";

    private String CREATE_TEMP_BOOK = "alter table book rename to _temp_book";

    private String INSERT_DATA = "insert into book select *,'' from _temp_book";

    private String DROP_BOOK = "drop table _temp_book";

 public DBservice(Context context, String name, CursorFactory factory,int version) {

  super(context, name, factory, version);

 }

 @Override

 public void onCreate(SQLiteDatabase db) {

  db.execSQL(CREATE_BOOK);

 }

 @Override

 public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

  switch (newVersion) {

  case 2:

   db.execSQL(CREATE_TEMP_BOOK);

   db.execSQL(CREATE_BOOK);

   db.execSQL(INSERT_DATA);

   db.execSQL(DROP_BOOK);

   break;

  }

 }


  • 2020-12-16 22:46:44

    基于coturn项目的stun/turn服务器搭建

    webrtc是google推出的基于浏览器的实时语音-视频通讯架构。其典型的应用场景为:浏览器之间端到端(p2p)实时视频对话,但由于网络环境的复杂性(比如:路由器/交换机/防火墙等),浏览器与浏览器很多时候无法建立p2p连接,只能通过公网上的中继服务器(也就是所谓的turn服务器)中转。示例图如下:

  • 2020-12-16 23:06:05

    Rocket.Chat推送信息

    Rocket.Chat推送消息 Rocket.Chat是一个开源实时通讯平台, 支持Windows, Mac OS, Linux. 支持聊天, 文件上传, 视频通话, 语音通话功能. 向Rocket.Chat推送消息 以下示例可以转为别的语言的版本, 本示例使用Linux平台的curl测试, curl非常强大. 登陆 首先需要登陆Rocket.Chat服务器

  • 2020-12-17 09:01:23

    对BitTorrent Tracker源码分析

    tracker服务器是BT下载中必须的角色。一个BT client 在下载开始以及下载进行的过程中,要不停的与 tracker 服务器进行通信,以报告自己的信息,并获取其它下载client的信息。这种通信是通过 HTTP 协议进行的,又被称为 tracker HTTP 协议,它的过程是这样的: client 向 tracker 发一个HTTP 的GET请求,并把它自己的信息放在GET的参数中;这个请求的大致意思是:我是xxx(一个唯一的id),我想下载yyy文件,我的ip是aaa,我用的端口是bbb。。。

  • 2020-12-17 10:55:48

    html5 video p2p research

    节约带宽,减少缓冲时间,提升服务质量,处理峰值流量, 视频观看的人越多,播放越流畅。

  • 2020-12-17 10:57:34

    使用 MediaSource 搭建流式播放器

    Media Source Extensions(媒体源扩展)大大地扩展了浏览器的媒体播放功能,提供允许JavaScript 生成媒体流。这可以用于自适应流(adaptive streaming,也是我毕设的研究方向)及随时间变化的视频直播流(live streaming)等应用场景。

  • 2020-12-17 11:00:37

    H5流式播放(FMP4转封装与mediaSource)

    W3C上有明确关于mediaSource 扩展接口的文档。mediaSource 扩展文档中是这么定义的, 它允许JS脚本动态构建媒体流用于和,允许JS传送媒体块到H5媒体元素。这种接口的应用可以让h5播放器实现持续添加数据进行播放。做as的朋友都知道as中的appendBytes方法,一种添加二进制数据进行播放的方式。这两种接口在概念上是类似的。只是里面的定义和对媒体文件的要求有所不同。对于mediaSource扩展接口我只介绍我们主要应用的几个。