请考虑如下情况:
在数据库升级时,不同版本的数据库,他们定义的表结构完全可能是不一样的,比如V1.0的表A有10个column,而在V1.1的表A有12个colum,在升级时,表A增加了两列,此时我们应该怎么做呢。
总体思路
1,将表A重命名,改了A_temp。
2,创建新表A。
3,将表A_temp的数据插入到表A。
下面代码列出了更新表的实现,upgradeTables,给定表名,更新的列名,就可以实现数据库表的更新。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
|
/**
* Upgrade tables. In this method, the sequence is:
* <b>
* <p>[1] Rename the specified table as a temporary table.
* <p>[2] Create a new table which name is the specified name.
* <p>[3] Insert data into the new created table, data from the temporary table.
* <p>[4] Drop the temporary table.
* </b>
*
* @param db The database.
* @param tableName The table name.
* @param columns The columns range, format is "ColA, ColB, ColC, ... ColN";
*/
protected
void
upgradeTables(SQLiteDatabase db, String tableName, String columns)
{
try
{
db.beginTransaction();
// 1, Rename table.
String tempTableName = tableName +
"_temp"
;
String sql =
"ALTER TABLE "
+ tableName +
" RENAME TO "
+ tempTableName;
execSQL(db, sql,
null
);
// 2, Create table.
onCreateTable(db);
// 3, Load data
sql =
"INSERT INTO "
+ tableName +
" ("
+ columns +
") "
+
" SELECT "
+ columns +
" FROM "
+ tempTableName;
execSQL(db, sql,
null
);
// 4, Drop the temporary table.
execSQL(db,
"DROP TABLE IF EXISTS "
+ tempTableName,
null
);
db.setTransactionSuccessful();
}
catch
(SQLException e)
{
e.printStackTrace();
}
catch
(Exception e)
{
e.printStackTrace();
}
finally
{
db.endTransaction();
}
}
|
得到数据库表的列名
我们可以通过SQL表得到表的列名。 这里需要注意的一点,int columnIndex = c.getColumnIndex("name"); 这里根据name去取得index。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
|
protected
String[] getColumnNames(SQLiteDatabase db, String tableName)
{
String[] columnNames =
null
;
Cursor c =
null
;
try
{
c = db.rawQuery(
"PRAGMA table_info("
+ tableName +
")"
,
null
);
if
(
null
!= c)
{
int
columnIndex = c.getColumnIndex(
"name"
);
if
(-
1
== columnIndex)
{
return
null
;
}
int
index =
0
;
columnNames =
new
String[c.getCount()];
for
(c.moveToFirst(); !c.isAfterLast(); c.moveToNext())
{
columnNames[index] = c.getString(columnIndex);
index++;
}
}
}
catch
(Exception e)
{
e.printStackTrace();
}
finally
{
closeCursor(c);
}
return
columnNames;
}
|
upgradeTables方法应该是在onUpgrade方法中去调用。
数据库升级的意义
在应用程序开发的过程中,数据库的升级是一个很重要的组成部分(如果用到了数据库),因为程序可能会有V1.0,V2.0,当用户安装新版本的程序后,必须要保证用户数据不能丢失,对于数据库设计,如果发生变更(如多添加一张表,表的字段增加或减少等),那么我们必须想好数据库的更新策略。
1,定义数据库版本
数据库的版本是一个整型值,在创建SQLiteOpenHelper时,会传入该数据库的版本,如果传入的数据库版本号比数据库文件中存储的版本号大的话,那么SQLiteOpenHelper#onUpgrade()方法就会被调用,我们的升级应该在该方法中完成。
2,如何写升级逻辑
假如我们开发的程序已经发布了两个版本:V1.0,V1.2,我们正在开发V1.3。每一版的数据库版本号分别是18,19,20。
对于这种情况,我们应该如何实现升级?
用户的选择有:
1) V1.0 -> V1.3 DB 18 -> 20
2) V1.1 -> V1.3 DB 19 -> 20
3,注意
数据库的每一个版本所代表的数据库必须是定义好的,比如说V18的数据库,它可能只有两张表TableA和TableB,如果V19要添加一张表TableC,如果V20要修改TableC,那么每一个版本所对应的数据库结构如下:
V18 ---> TableA, TableB
V19 ---> TableA, TableB, TableC
V20 ---> TableA, TableB, TableC (变更)
onUpgrade()方法的实现如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
// Pattern for upgrade blocks:
//
// if (upgradeVersion == [the DATABASE_VERSION you set] - 1){
// .. your upgrade logic..
// upgradeVersion = [the DATABASE_VERSION you set]
// }
public
void
onUpgrade(SQLiteDatabase db,
int
oldVersion,
int
newVersion)
{
int
upgradeVersion = oldVersion;
if
(
18
== 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);
}
}
|
从上面的代码可以看到,我们在onUpgrade()方法中,处理了数据库版本从18 -> 20的升级过程,这样做的话,不论用户从18 -> 20,还是从19 -> 20,最终程序的数据库都能升级到V20所对应的数据库结构。
4,如何保证数据不丢失
这是很重要的一部分,假设要更新TableC表,我们建议的做法是:
1) 将TableC重命名为TableC_temp
SQL语句可以这样写:ALERT TABLE TableC RENAME TO TableC_temp;
2) 创建新的TableC表
3) 将数据从TableC_temp中插入到TableC表中
SQL语句可以这样写:INSERT INTO TableC (Col1, Col2, Col3) SELECT (Col1, Col2, Col3) FROM TableC_temp;
经过这三步,TableC就完成了更新,同时,也保留了原来表中的数据。
注意:
在onUpgrade()方法中,删除表时,注意使用事务处理,使得修改能立即反应到数据库文件中。
本文转自java豆子博客园博客,原文链接:http://www.cnblogs.com/error404/p/3738630.html,如需转载请自行联系原作者