当前位置:网站首页>【数据库】sqlite版本升级、降级
【数据库】sqlite版本升级、降级
2022-06-12 11:32:00 【ScriptGirl】
参考:https://www.jianshu.com/p/65923fa3e3dc
1 正常全部使用流程
1.1 定义全局变量
public static SQLiteHelper dbHelper;
public static String folder = "android.xxx.xxx"; // 数据库保存地址
public static String file = "database.db"; // 数据库名称
public static int DB_VERSION = 1; // 数据库的版本号
public static SQLiteDatabase db; // 数据库
1.2 初始化数据库(在MainActivity中或者Services中)
这样得到的数据库保存在公共文件夹,即使卸载APP,数据库也不会丢失。
static void init_db(Context context) {
String pathname = GetDir.getDir(Constant.folder);
File file = new File(pathname, Constant.file);
try {
if(!file.exists()){
file.createNewFile();
Uri uri = Uri.fromFile(file);
Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, uri);
context.sendBroadcast(intent);
}
} catch (IOException e) {
Log.v("main", "failed1");
e.printStackTrace();
}
try {
Constant.dbHelper = new SQLiteHelper(context, pathname+"/"+Constant.file, null, Constant.DB_VERSION);
Constant.db = Constant.dbHelper.getWritableDatabase(); // 调用SQLiteHelper.OnCreate()
Log.v("main", "new db");
} catch (IllegalArgumentException e) {
Log.v("main", "failed2");
e.printStackTrace();
Constant.dbHelper.onUpgrade(Constant.db, Constant.DB_VERSION - 1, Constant.DB_VERSION);
}
}
其中GetDir.getDir如下:
public class GetDir {
public static String getDir(String pathname) {
String sdcardPath = Environment.getExternalStorageDirectory().toString();
File dir = new File(sdcardPath + File.separator + pathname /*+ File.separator + "Files"*/);
if (dir.exists()) {
return dir.toString();
} else {
dir.mkdirs();
return dir.toString();
}
}
}
1.3 在SQLiteHelper中定义数据库初始化的步骤,数据库升级和降级的操作
public class SQLiteHelper extends SQLiteOpenHelper {
static final String TAG = "SQLiteHelper";
public SQLiteHelper(Context context, String name, CursorFactory factory, int version) {
super(context, name, factory, version);
}
/** * 创建新表 */
@Override
public void onCreate(SQLiteDatabase db) {
Log.v(TAG,"onCreate");
db.execSQL("CREATE TABLE IF NOT EXISTS mytable (name varchar(15), age varchar(5))");
}
@Override
public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) {
Log.v(TAG,"onDowngrade");
if(oldVersion == 3 && newVersion == 2){
// 从3降到2
Log.i(TAG, "onDowngrade: 从3降到2");
db.execSQL("create table tmp_mytable as select name, age from mytable"); // 根据旧表创建新表,相当于删除score列
db.execSQL("drop table mytable");
db.execSQL("alter table tmp_mytable rename to mytable");
}
}
/** * 当检测与前一次创建的数据库版本不一样时,先删除表再创建新表 */
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
Log.v(TAG,"onUpgrade");
switch (newVersion){
case 2: {
// 给表添加score字段,并赋初值0
Log.i(TAG, "onUpgrade: newVersion = 2");
// 方式1
db.execSQL("alter table mytable add score varchar(5)");
ContentValues values = new ContentValues();
values.put("score", "0");
db.update("mytable ", values, "name!=?", new String[]{
""});
// 方式2
// 先创建符合要求的临时表
db.execSQL("CREATE TABLE IF NOT EXISTS mytable (name varchar(15), age varchar(5), score varchar(5))");
// 将数据从旧表复制到临时表
ContentValues values = new ContentValues();
values.put("score", "0");
db.execSQL("INSERT INTO tmp_mytable (name, age) SELECT name, age from mytable");
db.update("tmp_mytable", values, "name!=?", new String[]{
""}); // 只要name不为空,都修改score为0
// 删除旧表
db.execSQL("DROP TABLE IF EXISTS mytable");
// 将临时表重命名为旧表名
db.execSQL("ALTER TABLE tmp_mytable RENAME TO mytable");
break;
}
case 3: {
// 删掉两个表中的region字段
Log.i(TAG, "onUpgrade: newVersion = 3");
db.execSQL("create table tmp_mytable as select name, age from mytable"); // 若写 where 1 = 2 则只会复制表结构,不复制内容
db.execSQL("drop table mytable");
db.execSQL("alter table tmp_mytable rename to mytable");
break;
}
default:
break;
}
}
}
2. sqlite版本升级
2.1 方法1 硬升级 不推荐
首先是一种硬升级的方法,删除所有的所有旧表,然后重新创建数据库中的所有表。这种方法不够优雅,删除数据存在无法恢复的风险,不推荐这种方式。
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// 硬升级
db.execSQL("DROP TABLE IF EXISTS numbers");
db.execSQL("DROP TABLE IF EXISTS recordInfo");
onCreate(db);
2.2 推荐方法2种如下
/** * 当检测与前一次创建的数据库版本不一样时,先删除表再创建新表 */
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
Log.v(TAG,"onUpgrade");
switch (newVersion){
case 2: {
// 给表添加score字段,并赋初值0
Log.i(TAG, "onUpgrade: newVersion = 2");
// 方式1
// 先检查是否已经有score字段,如果没有,才给它升级
ContentValues values = new ContentValues();
values.put("score", "0");
if(!checkColumnExist(db, "mytable", "score")){
db.execSQL("alter table mytable add score varchar(5)");
db.update("mytable", values, "name!=?", new String[]{
""});
}
// 方式2
// 先创建符合要求的临时表
db.execSQL("CREATE TABLE IF NOT EXISTS mytable (name varchar(15), age varchar(5), score varchar(5))");
// 将数据从旧表复制到临时表
ContentValues values = new ContentValues();
values.put("score", "0");
db.execSQL("INSERT INTO tmp_mytable (name, age) SELECT name, age from mytable");
db.update("tmp_mytable", values, "name!=?", new String[]{
""}); // 只要name不为空,都修改score为0
// 删除旧表
db.execSQL("DROP TABLE IF EXISTS mytable");
// 将临时表重命名为旧表名
db.execSQL("ALTER TABLE tmp_mytable RENAME TO mytable");
break;
}
case 3: {
// 删掉两个表中的region字段
Log.i(TAG, "onUpgrade: newVersion = 3");
db.execSQL("create table tmp_mytable as select name, age from mytable"); // 若写 where 1 = 2 则只会复制表结构,不复制内容
db.execSQL("drop table mytable");
db.execSQL("alter table tmp_mytable rename to mytable");
break;
}
default:
break;
}
}
}
检查某表列是否存在
/** * 检查某表列是否存在 * @param db * @param tableName 表名 * @param columnName 列名 * @return */
private boolean checkColumnExist(SQLiteDatabase db, String tableName, String columnName) {
boolean result = false ;
Cursor cursor = null ;
try{
//查询一行
cursor = db.rawQuery( "SELECT * FROM " + tableName + " LIMIT 0", null );
result = cursor != null && cursor.getColumnIndex(columnName) != -1 ;
}catch (Exception e){
Log.e(TAG,"checkColumnExists1..." + e.getMessage()) ;
}finally{
if(null != cursor && !cursor.isClosed()){
cursor.close() ;
}
}
return result ;
}
2. 降级
@Override
public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) {
if(oldVersion == 3 && newVersion == 2){
// 从3降到2
Log.i(TAG, "onDowngrade: 从3降到2");
db.execSQL("create table tmp_mytable as select name, age from mytable");
db.execSQL("drop table mytable");
db.execSQL("alter table tmp_tb1 rename to mytable");
}
}
边栏推荐
- AcWing 1921. Rearranging cows (ring diagram)
- Windows10 install mysql-8.0.28-winx64
- Sendmail Dovecot 邮件服务器
- Face recognition PIP failed to install Dlib Library
- Lambda expression | shallow solution
- K52. Chapter 1: installing kubernetes v1.22 based on kubeadm -- cluster deployment
- B+ 树的简单认识
- Zabbix 监控之LLD
- AcWing 1986. 镜子(模拟,环图)
- 2022-06-11: note that in this document, graph is not the meaning of adjacency matrix, but a bipartite graph. In the adjacency matrix with length N, there are n points, matrix[i][j]
猜你喜欢

DS18B20 digital thermometer (I) electrical characteristics, parasitic power supply mode and remote wiring

redis 總結

Clj3-100alh30 residual current relay

M-arch (fanwai 10) gd32l233 evaluation -spi drive DS1302

AcWing 132. Group queue (queue simulation question)

模块8作业
![[Blue Bridge Cup SCM 11th National race]](/img/da/3c8a9efd5b28f67816f239531a0339.png)
[Blue Bridge Cup SCM 11th National race]

Don't swallow rice with vinegar! Teach you 2 moves to make the fish bones "run out" safely

Basic principle of Doppler effect

890. find and replace mode
随机推荐
Shardingjdbc-5.1.0 monthly horizontal table splitting + read-write separation, automatic table creation and node table refresh
6.6 分离卷积
Lambda表达式 | 浅解
Pytoch notes
B+ 树的简单认识
DS18B20 digital thermometer (I) electrical characteristics, power supply and wiring mode
The reason why scanf return value is ignored and its solution
Epidemic home office experience | community essay solicitation
Construction and construction of meta Universe System
Socket programming UDP
【藍橋杯單片機 國賽 第十一届】
Using stairs function in MATLAB
Process creation and recycling
Selenium uses proxy IP
AcWing 1921. Rearranging cows (ring diagram)
VirtualBox 虚拟机因系统异常关机虚拟机启动项不见了
AcWing 131. The largest rectangle in the histogram (monotone stack classic application template)
Signal relay rxsf1-rk271018dc110v
2022-06-11:注意本文件中,graph不是邻接矩阵的含义,而是一个二部图。 在长度为N的邻接矩阵matrix中,所有的点有N个,matrix[i][j]
十折交叉验证代码中的问题