Android數據庫Sqlite的基本用法及升級策略

SQLite簡介

SQLite是一款輕型的數據庫,是遵守ACID的關聯式數據庫管理系統,它的設計目標是嵌入 式的,而且目前已經在很多嵌入式產品中使用了它,它佔用資源非常的低,在嵌入式設備中,可能只需要幾百K的內存就夠了。它能夠支持 Windows/Linux/Unix等等主流的操作系統,同時能夠跟很多程序語言相結合,比如Tcl、PHP、Java、C++、.Net等,還有ODBC接口,同樣比起 Mysql、PostgreSQL這兩款開源世界著名的數據庫管理系統來講,它的處理速度比他們都快。

SQLite數據類型

一般數據採用的固定的靜態數據類型,而SQLite採用的是動態數據類型,會根據存入值自動判斷。SQLite具有以下五種常用的數據類型:

NULL: 這個值爲空值

VARCHAR(n):長度不固定且其最大長度爲 n 的字串,n不能超過 4000。

CHAR(n):長度固定爲n的字串,n不能超過 254。

INTEGER: 值被標識爲整數,依據值的大小可以依次被存儲爲1,2,3,4,5,6,7,8.

REAL: 所有值都是浮動的數值,被存儲爲8字節的IEEE浮動標記序號.

TEXT: 值爲文本字符串,使用數據庫編碼存儲(TUTF-8, UTF-16BE or UTF-16-LE).

BLOB: 值是BLOB數據塊,以輸入的數據格式進行存儲。如何輸入就如何存儲,不改 變格式。

DATA :包含了 年份、月份、日期。

TIME: 包含了 小時、分鐘、秒。

數據庫SQL增刪改查語句:

sql語句不區分大小寫

  • 查找:
    select column1,column2 from table_name
    或者
    select * from table_name

  • 插入:
    insert into table_name(column1,column2) values (value1,value2)

  • 更新:
    更新已有表的數據:
    update table_name set column1 = value1, column2 = value2
    where +條件語句

向表中插入列:
alter table table_name add column column_name text(varchar(10)、char等)

  • 刪除:
    delete from table_name where +條件語句

數據庫創建:

首先創建一個類去繼承SQLiteOpenHelper,創建一個test.db的數據庫

public class DBHelper extends SQLiteOpenHelper {

    private static final String DB_NAME = "test.db";
    public static final int DB_VERSION = 1;


    public DBHelper(Context context) {
        super(context, DB_NAME, null, DB_VERSION);
    }

    @Override
    public void onCreate(SQLiteDatabase database) {
        database.execSQL(DBDao.SQL_CREATE_TABLE);
    }

    @Override
    public void onUpgrade(SQLiteDatabase database, int oldVersion, int newVersion) {
    }

}

其中onCreate()是在數據庫首次創建的時候調用,onUpgrade()是在數據庫版本號DB_VERSION升級的時候纔會調用

封裝增刪改查方法:

public class DBDao {

    public static final String TABLE_NAME = "student";//表名

    private static final String ID = "id";//id自增長
    private static final String NAME = "stu_name";//姓名
    private static final String AGE = "stu_age";//年齡
    private static final String SEX = "stu_sex";//性別
    private static final String GRADE = "stu_grade";//年級
    //DB_Version2增加新字段
    private static final String SCORE = "store";

    private DBHelper dbHelper;

    //創建表結構
    public static final String SQL_CREATE_TABLE = "create table " + TABLE_NAME + "(" +
            ID + " integer primary key autoincrement," +
            NAME + " text," +
            AGE + " integer," +
            SEX + " varchar(5)," +
            GRADE + " text" +
            ")";


    private DBDao() {
        dbHelper = new DBHelper(MyApplication.getContext());
    }

    public static DBDao getInstance() {
        return InnerDB.instance;
    }

    private static class InnerDB {
        private static DBDao instance = new DBDao();
    }

    /**
     * 數據庫插入數據
     *
     * @param bean 實體類
     * @param <T>  T
     */
    public synchronized <T> void insert(T bean) {
        SQLiteDatabase db = dbHelper.getWritableDatabase();
        try {
            if (bean != null && bean instanceof Student) {
                Student student = (Student) bean;
                ContentValues cv = new ContentValues();
                cv.put(NAME, student.getName());
                cv.put(AGE, student.getAge());
                cv.put(SEX, student.getSex());
                cv.put(GRADE, student.getGrade());
                cv.put(SCORE, student.getStore());
                db.insert(TABLE_NAME, null, cv);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            db.close();
        }
    }

    /**
     * 刪除表中所有的數據
     */
    public synchronized void clearAll() {
        SQLiteDatabase db = dbHelper.getWritableDatabase();
        String sql = "delete from " + TABLE_NAME;

        try {
            db.execSQL(sql);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            db.close();
        }
    }

    /**
     * 查詢數據
     *
     * @return List
     */
    public synchronized <T> List<T> query() {
        SQLiteDatabase db = dbHelper.getReadableDatabase();
        List<T> list = new ArrayList<>();
        String querySql = "select * from " + TABLE_NAME;
        Cursor cursor = null;
        try {
            cursor = db.rawQuery(querySql, null);
            while (cursor.moveToNext()) {
                Student student = new Student();
                student.setName(cursor.getString(cursor.getColumnIndex(NAME)));
                student.setAge(cursor.getInt(cursor.getColumnIndex(AGE)));
                student.setSex(cursor.getString(cursor.getColumnIndex(SEX)));
                student.setGrade(cursor.getString(cursor.getColumnIndex(GRADE)));
                student.setStore(cursor.getString(cursor.getColumnIndex(SCORE)));
                list.add((T) student);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (cursor != null) {
                cursor.close();
            }
            if (db != null) {
                db.close();
            }
        }
        return list;
    }

}

創建實體類:

public class Student {
    private String name;
    private int age;
    private String grade;
    //Version2添加
    private String sex;

    public String getStore() {
        return store;
    }

    public void setStore(String store) {
        this.store = store;
    }

    private String store;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getGrade() {
        return grade;
    }

    public void setGrade(String grade) {
        this.grade = grade;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public Student() {
    }

    public Student(String name, int age, String grade, String sex,String store) {
        this.name = name;
        this.age = age;
        this.grade = grade;
        this.sex = sex;
        this.store=store;
    }
}

執行數據庫操作:

Student student = new Student("小明", 20, "三年二班", "man");
DBDao.getInstance().insert(student);

insert()方法中調用了dbHelper.getWritableDatabase(),此時沒有test.db數據庫則會去創建,接着執行onCreate()去創建了student表並插入了一條數據,去data/data/package_name/databases下查看發現test.db已經被創建好了,並且表中已經有了插入的數據,如下:

S71029-14273028.jpg

到此我們已經完成了基本的數據庫創建過程。

數據庫升級:

在版本迭代的過程中,我們難免不了要去改變我們數據庫的內容,此時就要考慮我們的數據庫升級問題了,假如此時我們有個需求,要在新的版本中在數據庫表中新加一個字段,首先我們要把DB_VERSION提升到2,那麼安裝新版本APK的時候就會執行onUpdate()操作去執行更新操作,那麼我們直接把更新的操作放到onUpdate()就可以了嗎?當然不行!我們要考慮各個版本的情況,比如用戶沒有安裝過1.0版本,直接安裝的2.0版本,那麼這種情況是不會執行onUpdate()方法的,以後有了3.0、4.0版本,邏輯將更復雜,所以單純的放到onUpdate()中是不可行的,還有一種方式:

  @Override
  public void onCreate(SQLiteDatabase database) {
      database.execSQL(DBDao.SQL_CREATE_TABLE);
  }

  @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        try {
            db.execSQL("DROP TABLE IF EXISTS student");
            this.onCreate(db);
        } catch (Exception e) {
        }

    }

這種的在更新時直接把原來的表刪除掉然後手動去調onCreate()去重建表,個人覺得不夠優雅,首先老數據會丟失,假如要手動保存,表中數據量大時操作起來也不方便,那麼有沒有更好一些的方法呢?看下面這種方式:

    private static final String DB_NAME = "test.db";
    public static final int DB_VERSION = 2;

    @Override
    public void onCreate(SQLiteDatabase database) {
        int initDBVersion = 1;
        DataBaseHelper.initDB(database);
        onUpgrade(database, initDBVersion, DB_VERSION);
    }

    @Override
    public void onUpgrade(SQLiteDatabase database, int oldVersion, int newVersion) {
        for (int i = oldVersion; i < newVersion; i++) {
            switch (i) {
                case 1:
                    DataBaseHelper.upToDbVersion2(database);
                    break;
                case 2:
                    DataBaseHelper.upToDbVersion3(database);
                    break;
                default:
                    break;
            }
        }
    }

如果用戶是從1.0升到2.0的,那麼會直接執行onUpdate(),此時oldVersion是1,執行for循環中的DataBaseHelper.upToDbVersion2(database),如果用戶沒有裝過1.0版本而是直接安裝的2.0版本,那麼會執行onCreate()方法,在onCreate()中手動調用的onUpdate()方法去執行更新操作,這樣就兼容到了各種需求,同時升級到3.0、4.0版本都是可以兼容的,比如在2.0時想在原有表中新加一列:

 public static void upToDbVersion2(SQLiteDatabase database) {
     String updateSql = "alter table " + DBDao.TABLE_NAME + " add column store varchar(5)";
     database.execSQL(updateSql);
 }

S71029-14285063.jpg

升級到3.0時想把列store中的值全改成100:

 public static void upToDbVersion3(SQLiteDatabase database) {
     ContentValues values = new ContentValues();
     values.put("store", 100);
     database.update(DBDao.TABLE_NAME, values, null, null);
 }

S71029-14580506.jpg

實驗結果可知,各種情況都可以兼容,個人覺得這種方案更好一些,注意數據庫的版本號只能升級,不能降級,例如不能將數據庫版本號從2降到1:

Caused by: android.database.sqlite.SQLiteException: Can't downgrade database from version 2 to 1

源碼地址:http://download.csdn.net/download/u013700502/10043778

參考:http://www.w3school.com.cn/sql/index.asp
http://www.runoob.com/sqlite/sqlite-update.html
http://blog.csdn.net/codeeer/article/details/30237597/

發佈了53 篇原創文章 · 獲贊 98 · 訪問量 10萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章