Android 数据库进阶之数据库升级连带保存数据
今天得空,写一篇文章,是关于Android数据库的。每个应用都需要对数据进行存储和更改,当然一些简单的数据,数据比较少,就不必用数据库存数,可以用Android提供的SharedPreferences,这个相对数据库存取数据来说消耗的资源更少,而且存储方式更容易让人理解。Android使用的是开源的、与操作系统无关的SQL数据库—SQLite。它是一款轻量级数据库,它的设计目标是嵌式的,占用资源同样也非常的低。
简单的介绍了下Android用的数据库,但是今天我不会给大家带来数据库的创建和存储数据等操作的实现,Sql语句比较好写,而且相信很多人也会创建数据库的,我这里带来的问题解决,主要是针对数据库创建完之后,APP已经成功上线,可是由于产品的需求,需要针对数据库中的表进行字段的增加,也就是需要进行数据库升级。
举个例子就是上线的数据库是V1.0,有8个column,但是现在版本升级,也要升级数据库V1.1,要追加2个column,现在我们该怎么办?问题既然来了,那我们就给出解决方案。
这是我们原有的数据库表:
CREAT_CARD="create table IF NOT EXISTS " + CARD + "(" + CardExportColumns.DATE + " char(16)," + CardExportColumns.FILE_NAME + " char(32)," + CardExportColumns.FILE_URI + " char(50)" + ");"
现在我要在这里面加一个time的标签,
CREAT_CARD="create table IF NOT EXISTS " + CARD + "(" + CardExportColumns.DATE + " char(16)," + CardExportColumns.FILE_NAME + " char(32)," + CardExportColumns.FILE_URI + " char(50)" + CardExportColumns.CREATE_TIME +" long" + ");"
大概思路:
1.将表名重命名
2.创建新表
3.将数据插入新表
4.删除临时表
现在我们用代码具体实现下:
CREATE_TEMP_CARD = "alter table card rename
to temp_card";//将表重命名
CREAT_CARD="create
table IF NOT EXISTS " + CARD + "(" + CardExportColumns.DATE + " char(16)," +
CardExportColumns.FILE_NAME + " char(32),"
+ CardExportColumns.FILE_URI + "
char(50)" + CardExportColumns.CREATE_TIME +" long" + ");"//创建新表
INSERT_DATA_INTO
= "insert into
card select *,"" from
temp_card";//(注意' '是为新加的字段插入默认值的必须加上,否则就会出错)
DROP_TEMP
= "drop table temp_card"; // 删除临时表
public class DbBase extends SQLiteOpenHelper {
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(CREATE_CARD);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
if(newVersiong>oldVersion){
db.execSQL(CREATE_TEMP_CARD);
db.execSQL(CREATE_CARD);
db.execSQL(INSERT_DATA_INTO);
db.execSQL(DROP_TEMP);
}
}
}
这样我们就完成了新加入一些字段,升级数据库,并保留之前的数据。
下面我再给大家提供一个方法,就是获得旧数据的字段值,
//
获取升级前表中的字段
protected String getColumnNames(SQLiteDatabase db, String tableName)
{
Cursor c = null;
try
{
c = db.rawQuery( "PRAGMA table_info(" + tableName + ")", null );
if (null != c)
{
String[]
columnNames = new String[cursor.getColumnCount()];
int count =c.getColumnCount();
for ( int i = 0;i<count ;i++)
{
coulunNames[i] = c.getgetColumnName(i);
}
}
}
catch (Exception e)
{
e.printStackTrace();
}
finally
{
if (c != null)
{
c.close();
}
}
return sb.toString();
}
}
数据库升级的逻辑,我觉得是很重要的,产品在开发之前就要想好升级策略,这样才能保证数据不会丢失。
比如现在我们发布了两个版本:V1.0,V1.1现在准备发布V1.2版本,在onUpgrade中我们判断的到是1.2和1.1,分别对应的版本号是10,11,12但是可能还存在V1.0的用户,所以我们就要做好V1.0的用户升级,数据库的升级策略还是很重要的。
public void onUpgrade(SQLiteDatabase
db, int oldVersion, int newVersion)
{
int upgradeVersion = oldVersion;
if (11 == upgradeVersion)
{
// Create table C
String sql = "CREATE TABLE ...";
db.execSQL(sql);
upgradeVersion = 19;
}
if (20 == upgradeVersion)
{
// Modify table C
upgradeVersion = 20;
}
if (upgradeVersion != newVersion) {
// Drop tables
db.execSQL("DROP TABLE IF EXISTS " + tableName);
// Create tables
onCreate(db);
}
}
当然添加的时候也可以用Sqlite提供的Alter字段,来增加字段或者更新字段,但是不能删除Column。增加字段,比如"Alter table " + CARD_TABLE_CARD + " add column " + CardColumns.OWNERSHIPOPT + " integer default -1",但是必须满足一下限制:
字段不能有主键或唯一约束。
字段不能有这些缺省值:CURRENT_TIME, CURRENT_DATE 或CURRENT_TIMESTAMP
若定义了NOT NULL约束,则字段必须有一个非空的缺省值。
而且这样添加字段的话,新字段只能添加到表的末尾,而且只能增加有限子集,而且对一些复杂的操作,比如要更改又要移动数据,效率比较低,比较麻烦。对于复杂的操作还是推荐用重命名表的方式。