說(shuō)說(shuō) Android 中的 SQLite 數(shù)據(jù)庫(kù)

SQLite 是一款輕量級(jí)的關(guān)系型數(shù)據(jù)庫(kù),它的運(yùn)算速度非常快, 占用資源很少,通常只需幾百 K 的內(nèi)存就足夠了,因而特別適合在移動(dòng)設(shè)備上使用。它不僅支持標(biāo)準(zhǔn)的 SQL 語(yǔ)法,還遵循了數(shù)據(jù)庫(kù)的 ACID 事務(wù)。這套數(shù)據(jù)庫(kù)可是內(nèi)置于 Android 系統(tǒng)中的哦O(∩_∩)O哈哈~

當(dāng)需要存儲(chǔ)大量復(fù)雜的關(guān)系型數(shù)據(jù)時(shí),就要用到關(guān)系型數(shù)據(jù)庫(kù)啦。

1 創(chuàng)建數(shù)據(jù)庫(kù)

Android 提供了一個(gè) SQLiteOpenHelper 幫助類,借助這個(gè)類可以非常簡(jiǎn)單地對(duì)數(shù)據(jù)庫(kù)進(jìn)行創(chuàng)建與升級(jí)。

SQLiteOpenHelper

SQLiteOpenHelper 是一個(gè)抽象類,所以我們需要?jiǎng)?chuàng)建一個(gè)類去繼承它并且重寫(xiě)它的兩個(gè)抽象方法,即 onCreate() 和 onUpgrade(),去實(shí)現(xiàn)創(chuàng)建、升級(jí)數(shù)據(jù)庫(kù)的邏輯。

創(chuàng)建或打開(kāi)一個(gè)現(xiàn)有的數(shù)據(jù)庫(kù)(若已存在則打開(kāi),否則創(chuàng)建一個(gè)新庫(kù)),并返回一個(gè)可對(duì)數(shù)據(jù)庫(kù)進(jìn)行讀寫(xiě)操作的對(duì)象的實(shí)例方法有兩種(getReadableDatabase、getWriableDatabase),它們之間的區(qū)別是,當(dāng)數(shù)據(jù)庫(kù)不可寫(xiě)入的情況下(如磁盤(pán)空間已滿):

方法 區(qū)別
getReadableDatabase() 返回的對(duì)象將以只讀的方式去打開(kāi)數(shù)據(jù)庫(kù)。
getWriableDatabase() 拋出異常。

SQLiteOpenHelper 中的一個(gè)構(gòu)造函數(shù)是這樣的:

SQLiteOpenHelper(Context context, String name, CursorFactory factory, int version)
參數(shù) 說(shuō)明
context 上下文
name 數(shù)據(jù)庫(kù)名
factory 自定義游標(biāo),不需要就傳入 null
version 當(dāng)前數(shù)據(jù)庫(kù)的版本號(hào),用于升級(jí)數(shù)據(jù)庫(kù)

構(gòu)建出 SQLiteOpenHelper 的實(shí)例后,再調(diào)用它的 getReadableDatabase() 或 getWritableDatabase() 方法就能夠創(chuàng)建數(shù)據(jù)庫(kù)咯,數(shù)據(jù)庫(kù)文件會(huì)存放在 /data/data/<package name>/databases/ 的目錄下。 此時(shí),重寫(xiě)的 onCreate() 方法也會(huì)得到執(zhí)行,可以在這里處理一些創(chuàng)建表的邏輯。

假設(shè)我們需要建立一個(gè)名為 People.db 的數(shù)據(jù)庫(kù),然后在這個(gè)數(shù)據(jù)庫(kù)中新建一張 people 表,表中有 id(主鍵)、名字、年齡、體重等字段。建表語(yǔ)句如下:

create table people( 
id integer primary key autoincrement,
name text,
age integer,
weight real)
數(shù)據(jù)類型 說(shuō)明
integer 整型
real 浮點(diǎn)型
text 文本類型
blob 二進(jìn)制類型

primary key autoincrement:表示設(shè)置某個(gè)字段為主鍵并且自增長(zhǎng)。

PeopleDatabaseHelper 類:

public class PeopleDatabaseHelper extends SQLiteOpenHelper {

    /**
     * 建表語(yǔ)句
     */
    public static final String CREATE_SQL="create table people( id integer primary key autoincrement,name text,age integer,weight real)";

    private Context context;

    public PeopleDatabaseHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
        super(context, name, factory, version);
        this.context=context;
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL(CREATE_SQL);
        Toast.makeText(context, "建表成功", Toast.LENGTH_SHORT).show();
    }

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

    }
}

我們?cè)?onCreate 方法中 使用了 execSQL 來(lái)執(zhí)行建表語(yǔ)句 ,這樣就可以在創(chuàng)建數(shù)據(jù)庫(kù)之后,創(chuàng)建需要的表。

調(diào)用語(yǔ)句:

 final PeopleDatabaseHelper helper=new PeopleDatabaseHelper(this,"People.db",null,1);
helper.getWritableDatabase();

可以使用 adb shell 來(lái)查看數(shù)據(jù)庫(kù)與表的創(chuàng)建情況。

adb 是 Android SDK 自帶的調(diào)試工具,可以直接對(duì)連接在電腦上的手機(jī)或者模擬器進(jìn)行開(kāi)發(fā)調(diào)試工作。它的安裝方法請(qǐng)參見(jiàn) 在 Android Device Monitor 的 File Explorer 中,無(wú)法打開(kāi)某些文件夾的解決方法

在命令行界面,使用命令 adb shell 進(jìn)入設(shè)備控制臺(tái)(先使用 adb root 獲得訪問(wèn)權(quán)限):

設(shè)備控制臺(tái)

進(jìn)入目錄命令的格式為:

cd /data/data/[包名]/databases/

這里為 cd /data/data/net.deniro.android.databasetest/databases/

進(jìn)入目錄

使用命令 ls 查看當(dāng)前目錄下的文件:

*.db:是我們創(chuàng)建的數(shù)據(jù)庫(kù)。
*.db-journal:是為了讓數(shù)據(jù)庫(kù)能夠支持事務(wù)所產(chǎn)生的臨時(shí)日志文件,一般情況下,它為 0 字節(jié)。

使用 sqlite3 數(shù)據(jù)庫(kù)名 來(lái)打開(kāi)數(shù)據(jù)庫(kù),并使用 .table 命令來(lái)查看目前的數(shù)據(jù)庫(kù)中有哪些表:

使用命令 .schema 可以查看這些表的創(chuàng)建語(yǔ)句:

鍵入 .exit 或 .quit 就可以退出 sqlite,再次鍵入 .exit 就會(huì)退出設(shè)備控制臺(tái),是不是很簡(jiǎn)單呀O(∩_∩)O哈哈~

2 升級(jí)數(shù)據(jù)庫(kù)

可以在繼承自 SQLiteOpenHelper 類的 onUpgrade 方法中,對(duì)數(shù)據(jù)庫(kù)進(jìn)行升級(jí)。

假設(shè)我們需要新增一張行業(yè)表,建表語(yǔ)句為:

create table Industry(
  id integer primary key autoincrement,
  industry_name text,
  industry_code integer)

修改原來(lái)的代碼:

/**
 * 創(chuàng)建行業(yè)表
 */
public static final String CREATE_INDUSTRY_SQL = "create table Industry(  id integer primary key autoincrement,  industry_name text,  industry_code integer)";

 @Override
public void onCreate(SQLiteDatabase db) {
    db.execSQL(CREATE_PEOPLE_SQL);
    db.execSQL(CREATE_INDUSTRY_SQL);
    Toast.makeText(context, "建表成功", Toast.LENGTH_SHORT).show();
}

@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    dropTable(db, "People");
    dropTable(db, "Industry");
    onCreate(db);
}

/**
 * 刪除表
 *
 * @param db
 * @param tableName 表名稱
 * @return
 */
private void dropTable(SQLiteDatabase db, String tableName) {
    db.execSQL("drop table if exists " + tableName);
}

這里首先在 onCreate 方法中,創(chuàng)建行業(yè)表;接著在 onUpgrade 方法中,刪除相應(yīng)的表,并調(diào)用 onCreate,重新創(chuàng)建表結(jié)構(gòu)。

最后在 PeopleDatabaseHelper 的構(gòu)造函數(shù)中,把版本號(hào)(最后一個(gè)參數(shù))改為 2:

創(chuàng)建成功后,可以通過(guò)之前介紹的 adb shell 方法查看新創(chuàng)建的表結(jié)構(gòu):


3 新增數(shù)據(jù)

對(duì)數(shù)據(jù)進(jìn)行的操作一般有四種,即 CRUD:添加(Create),查詢(Retrieve),更新(Update),刪除(Delete)。

SQLiteOpenHelper 中的 getReadableDatabase() 或 getWritableDatabase() 方法都會(huì)返回一個(gè) SQLiteDatabase 對(duì)象,借助這個(gè)對(duì)象可以對(duì)數(shù)據(jù)進(jìn)行 CRUD 操作。

SQLiteDatabase 類包含 insert 方法:

public long insert(String table, String nullColumnHack, ContentValues values)
參數(shù)名 說(shuō)明
table 表名
nullColumnHack 在未指定添加數(shù)據(jù)的情況下給某些可為空的列自動(dòng)賦值,一般傳入 null。
values 是一個(gè)ContentValues 對(duì)象,它包含一系列的 put() 方法重載,用于向 ContentValues 中添加數(shù)據(jù)(列名與列的內(nèi)容一一對(duì)應(yīng))。

新增操作:

SQLiteDatabase db= helper.getWritableDatabase();

//新增
ContentValues values=new ContentValues();
values.put("name","deniro");
values.put("age",22);
values.put("weight",70);
db.insert("People",null,values);

因?yàn)?id 為自增長(zhǎng)的列,所以這里無(wú)須賦值。

查看結(jié)果:

select * from People;

4 更新數(shù)據(jù)

SQLiteDatabase 類包含 update 方法:

public int update(String table, ContentValues values, String whereClause, String[] whereArgs) 
參數(shù)名 說(shuō)明
table 表名
values ContentValues 對(duì)象,存放要更新的數(shù)據(jù)
whereClause where SQL 語(yǔ)句(占位符形式)
whereArgs where SQL 語(yǔ)句中的參數(shù),與語(yǔ)句中的占位符一一對(duì)應(yīng)

調(diào)用代碼:

SQLiteDatabase db= helper.getWritableDatabase();

//修改
ContentValues values=new ContentValues();
values.put("age",24);
db.update("People",values,"name = ?",new String[]{"deniro"});

這里把所有 name = 'deniro' 的數(shù)據(jù)中的 age 都更新為 24。

更新結(jié)果:


5 刪除數(shù)據(jù)

SQLiteDatabase 類中包含 delete 方法來(lái)刪除數(shù)據(jù):

public int delete(String table, String whereClause, String[] whereArgs) 
參數(shù)名 說(shuō)明
table 表名
whereClause where SQL 語(yǔ)句(占位符形式)【可選】
whereArgs where SQL 語(yǔ)句中的參數(shù),與語(yǔ)句中的占位符一一對(duì)應(yīng)【可選】

調(diào)用代碼:

SQLiteDatabase db = helper.getWritableDatabase();

//刪除
db.delete("People", "name = ?", new String[]{"deniro"});

執(zhí)行后,在 sqlite 命令中就會(huì)發(fā)現(xiàn),數(shù)據(jù)被刪除咯。

6 查詢數(shù)據(jù)

SQLiteDatabase 中提供了 query() 方法用于查詢數(shù)據(jù)。 這個(gè)方法的參數(shù)非常復(fù)雜,最短的一個(gè)方法重載也需要傳入七個(gè)參數(shù)。

query 的各種重載方法
 public Cursor query(String table, String[] columns, String selection,
            String[] selectionArgs, String groupBy, String having,
            String orderBy)
參數(shù)名 說(shuō)明 示例
table 表名 from table_name
columns 列名 select column1,column2
selection where 條件 where column = value
selectionArgs where 條件中的占位符參數(shù)值 -
groupBy 需要分組的列 group by column
having 分組條件 having column = value
orderBy 排序條件 order by column1,column2

返回 Cursor 對(duì)象,查詢到的數(shù)據(jù)可以從這個(gè)對(duì)象中取出。

調(diào)用代碼:

SQLiteDatabase db = helper.getWritableDatabase();

//查詢
Cursor cursor = db.query("People", null, null, null, null, null, null);
if (cursor.moveToFirst()) {
    do {
        Log.d(TAG, "name: " + cursor.getString(cursor.getColumnIndex("name")));
        Log.d(TAG, "age: " + cursor.getInt(cursor.getColumnIndex("age")));
    } while (cursor.moveToNext());
}
cursor.close();

得到 Cursor 對(duì)象后,使用 moveToFirst 把數(shù)據(jù)指針移到第一行,然后進(jìn)入循環(huán)。getColumnIndex 獲取某一列在表中的位置索引,然后把這個(gè)索引傳入相應(yīng)類型的取值方法中(比如 int 型,使用 getInt 方法),就可以讀取數(shù)據(jù)啦。最后記得關(guān)閉 cursor。

7 使用原生 SQL 操作數(shù)據(jù)庫(kù)

我們也可以直接使用原生 SQL 來(lái)完成前面說(shuō)過(guò)的新增、修改與刪除操作,這就是 SQLiteDatabase 類中的 execSQL 方法:

public void execSQL(String sql, Object[] bindArgs)
參數(shù)名 說(shuō)明
sql SQL 語(yǔ)句
bindArgs 占位符綁定的參數(shù)

查詢數(shù)據(jù)可以使用 SQLiteDatabase 類中的 rawQuery方法:

 public Cursor rawQuery(String sql, String[] selectionArgs)

參數(shù)說(shuō)明與 execSQL 方法類似,是不是很簡(jiǎn)單呀O(∩_∩)O哈哈~

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容