2016年2月12日 星期五

Android 的 SQLite 學習筆記

Android 內建可使用 SQLite 資料庫。但是 SQLite 是屬於內建在系統裡面的 Database,如果資料量不多的話,可以考慮使用。 (通常我是不太用 SQLite, 我都接 API 的比較多...,但如果不是一些很重要的資料,只打算存在該支手機上的資料,我也會用這種方式存 XD)


openOrCreateDatabase
如果要建立一個資料庫,使用 SQLite 要 import android.database.sqlite.SQLiteDatabase,接著呼叫 openOrCreateDatabase 方法。如: SQLiteDatabase 物件名稱 = openOrCreateDatabase(資料庫檔名, 存取權限, null)。

參數第一個是資料庫檔名; 第二個是存取權限; 第三個是 ErrorHandler,如果你不打算處理 Error 的情況,就塞 null 進去,或是就乾脆不要放第三個參數。


openOrCreateDatabase這個方法如其名,就是當指定的資料庫檔名不存在的話,就會 create 一個新的。 資料庫副檔名是 .db。不指定副檔名也 ok.

至於存取權限,依照你的 App 設計,看你想怎麼調整,三種選擇:
1. MODE_PRIVATE 只有這個 app 可以存取。
2. MODE_WORLD_READABLE 所有的 APP 都可以來讀取。
3. MODE_WORLD_WRITEABLE 所有的 APP 都可以來寫入。


Ex: 建立一個叫做 demo 的資料庫,且只有本身的 app 可以存取,不處理 errorHandler:
SQLiteDatabase db = openOrCreateDatabase("demo.db", MODE_PRIVATE, null);
openOrCreateDatabase 會回傳一個 SQLiteDatabase 物件,並延續使用這個物件來操作該資料庫。

接著來介紹一下拿到這個回傳的 SQLiteDatabase 物件可以做哪些操作:
1. 建立資料表 (有庫才有表嘛,這邊我就不介紹資料庫的事情了...)。
2. 針對資料表做資料的增修刪讀。

execSQL()
利用 SQLiteDatabase 建立的物件,如上例 db,可執行 execSQL() 方法來執行 SQL 語句。 不過 execSQL 並沒有回傳值。


execSQL 語法最煩的地方就是你要會寫 SQL 而已,可以用 execSQL 來建立一個資料表在資料庫裡面。其他操作也是,只要會寫 SQL 就可以透過 execSQL 操作資料庫, 以及資料表的增修刪讀。

// 建立 SQLiteDatabase 物件
SQLiteDatabase db = openOrCreateDatabase("demo.db", MODE_PRIVATE, null);
// 建立 user 資料表的 SQL
String createUserTable = "" +
"CREATE TABLE users(id INTEGER PRIMARY KEY, name VARCHAR)";
// 執行 SQL
db.execSQL(createUserTable);

(建議把 CREATE TABLE... 改成 CREATE TABLE IF NOT EXISTS)



insert(), update()


* insert(String 資料表名稱, String nullColumnHack, ContentValue 物件);
* update(String 資料表名稱ContentValue 物件, String whereClause, String[] whereArgs)

insert 用來新增一筆記錄到資料表。update 用來更新某筆資料。
比較特別的是使用 insert, update,必須先建立 ContentValues 物件(需要 import android.content.ContentValues;),並且用 put() 的方式把資料打進 ContentValues 物件裡,再把 ContentValues 餵進 insert(), upadte() 的 ContantValues 那個參數位置。

第二個參數是 nullColumnHack,通常會給 null。nullColumnHack 想知道用法的話,可以參考這篇文章: android之SQLite数据库insert操作

Ex: 建立一筆資料到 user 的資料表:
// 新增一筆記錄到 users
// 1. 首先 先建立 ContentValues 物件
ContentValues user1 = new ContentValues();
// 2. 指定 name 欄位的值
user1.put("name", "吳肥穎");
// 3. insert user1 的ContentValues 物件到資料表:users
db.insert("users", null, user1);

update() 參數比較不一樣一點,為什麼應該很好猜吧?! 因為 update 需要指定是哪一筆資料要被更新,甚至可以多帶 WhereArgs 。

Ex: 更新在 users 資料表 id 為 1 的 name 為 WinWu
// 更新 id 為 1 的 name 為 WinWu
ContentValues updateUser1 = new ContentValues();
updateUser1.put("name", "winwu");
db.update("users", updateUser1, "id=1", null);


delete()
刪除的方法為 delete(),他是用來刪除資料表的紀錄:
delete(String table, String whereClause, String[] whereArgs)

第一個參數指定資料表名稱,第二個為刪除的指標是哪一個。
如果你沒有指定 whereClause,帶 null 的話,則會刪除整張表的 row。

Ex: 刪除 id 為 1 的 users 資料
// 刪除 id 為1 的 users 資料
db.delete("users", "id=1", null);


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

rawQuery 用來查資料。但是他比較囉唆一點,跟 execSQL 比起來,rawQuery 會回傳資料,而且回傳的型別是 Cursor 型別 ,所以使用 rawQuery 記得用 Cursor 型別的物件把回傳值接起來 (要 import android.database.Cursor;)。

第一個參數是執行的 SQL,第二個參數是對應的符號查詢條件,如果你第一個參數 SQL 帶有 ? 的查詢格式,那麼第二個參數就要用字串陣列的方式把查詢條件的值帶進去。

Ex: 查詢 users 這張表的紀錄,因為 SQL 沒有 ? 查詢條件,因此第二個參數為 null。
Cursor userResult =  db.rawQuery("SELECT * FROM users", null);

Ex: 另一種寫法
Cursor userResult =  db.rawQuery("SELECT * FROM users WHERE id = ?", new String[]{"1"});

用 rawQuery() 做查詢我偏好 ? 的方式,感覺比較乾淨一點。雖然 rawQuery 很方便,但是怎麼 iterate 回傳的 Cursor 需要看看文件了。

回傳的 Cursor 有很多 method 可以用,像是 move(), moveToPosition(), moveToFirst(), moveToLast().....。google 一下怎麼 loop 查詢的 cursor 結果,通常 SOP 都跟做 web 很像,先看 cursor 的總筆數 (getCount()) 是不是大於 0,然後就開始 loop,只要不是最後一筆,就繼續拿下一筆 (moveToNext) 之類的邏輯 XD 這裏只是舉例..


close()
關閉資料庫,習慣上放在 Activity 的 onDestroy 的方法裡 (有的人會放在 onStop),當 user 把 App 關閉後,也就順便讓資料庫關閉。 參考: Android SQLite DB When to Close
@Override
protected void onDestroy() {
    super.onDestroy();
    db.close();
}


匯入匯出資料庫
如果有 demo 用的 SQLite 資料檔案的話,可以用 Android Device Monitor 進行匯入資料庫。當然也可以匯出...



打開 Monitor 之後,在 File Explorer 找到 data/data/你的 app 名稱/database 資料夾,然後利後右上角那兩顆 icon,匯入或是匯出。

後記
小的知識淺薄,有寫錯之處還希望大家留言幫忙指正。謝謝!

雖然我很不常用 SQLite,不過 SQLite 支援大部份的 SQL 語法,相信使用上學習的曲線不會太長。另外如果內建的 method 不夠使用的話,或者是自己的專案的 Business Login 太複雜的話,也可以自己寫一個 Database 的 Class 來使用。

好文連結:
Android 6 Tutorial 第三堂(3)使用Android內建的SQLite資料庫
https://github.com/macdidi5/Android-6-Tutorial

沒有留言:

張貼留言

若你看的文章,時間太久遠的問題就別問了,因為我應該也忘了... XD

Vue multiselect set autofocus and tinymce set autofocus

要在畫面一進來 focus multiselect 的方式: 參考: https://jsfiddle.net/shentao/mnphdt2g/ 主要就是在 multiselect 的 tag 加上 ref (例如: my_multiselect), 另外在 mounted...