close
Android使用SQLite資料庫


Android內建的SQLite為開放式的小型資料庫,應用程式可以建立自己需要的資料庫,並使用Android API做管理與查詢的工作
特色為支援精簡「SQL」指令、效能好、相對其它資料庫使用更少的記憶體,因為所有資料都儲存在一個檔案當中,所以在移轉資料時也非常便利

在此先來說一下資料表格,這是用來劃分各個欄位儲存不同資料,例如整理班級考試成績,就會有班級、學號、各項成績....等各項欄位
而欄位的分為以下幾種資料型態:

INTEGER – 整數,對應Java 的byte、short、int 和long。
REAL – 小數,對應Java 的float 和double。
TEXT – 字串,對應Java 的String。



介紹SQLiteOpenHelper類別

Android 中可以透過繼承SQLiteOpenHelper來建立資料庫與表格,後續執行時開啟建立好的資料庫
建立資料庫表格使用SQL的「CREATE TABLE」指令,且需指定表格名稱,還有各個欄位名稱與資料型態
而表格內一定要包含一個可以自動為資料編號的欄位,欄位名稱固定為「_id」,型態為「INTEGER」,後面加上「PRIMARY KEY AUTOINCREMENT」的設定,將能設為主鍵且自動增加,保證裡面的資料是唯一的,而其他欄位型態後面可選擇是否加上「NOT NULL」,該欄位就不可以為空值,如果新增資料時沒有指定該欄位設值將會發生錯誤


使用SQL可分為以下四個動作,等等會在範例中一一使用

1.新增記錄(Insert)。
2.查詢記錄(Query)。
3.更改記錄(Update)。
4.刪除記錄(Delete)。

以下先來決定資料表的欄位,如果範例為多人聊天紀錄,就必須有以下欄位:


1.用來判斷第幾筆資料的主鍵的:_id
2.聊天紀錄說話者姓名:name
3.說的內容:content
4.字的顏色:color
5.多人聊天的玩家號碼:number

先來設定一下幾種文字顏色,範例為:

package com.example.sqlite;
import android.graphics.Color;
public enum Colors {
    //能在列舉內實作幾個物件
    LIGHTGREY("#D3D3D3"), BLUE("#33B5E5"), PURPLE("#AA66CC"), 
    GREEN("#99CC00"), ORANGE("#FFBB33"), RED("#FF4444");
    private String code;
    private Colors(String code) {    //建構子設為private因為只在物件內實作出物件
        this.code = code;
    }
    public String getCode() {    //取得顏色的String
        return code;
    }
    public int parseColor() {    //使用Color解析code
        return Color.parseColor(code);
    }
}


設定完顏色後,再來針對各個欄位的資料寫一個物件方便存取,範例為:

package com.example.sqlite;
import java.io.Serializable;
@SuppressWarnings("serial")
public class Item implements Serializable{    //介面為物件序列化,可將物件變成二進位串流,就可儲存成檔案,也可以直接將物件丟進輸出入串流做傳送
    private long id;
    private String name;
    private String content;
    private Colors color;
    private long number;
    public Item(){
        content = "";
        color = Colors.LIGHTGREY;
    }
    public Item(long id,String name,String content,Colors color,long number){
        this.id=id;
        this.name=name;
        this.content=content;
        this.color=color;
        this.number=number;
    }
    public void setId(long id){
        this.id=id;
    }
    public long getId(){
        return this.id;
    }
    public void setName(String name){
        this.name=name;
    }
    public String getName(){
        return this.name;
    }
    public void setContent(String content){
        this.content=content;
    }
    public String getContent(){
        return this.content;
    }
    public void setColor(Colors color){
        this.color=color;
    }
    public Colors getColor(){
        return this.color;
    }
    public void setNumber(long number){
        this.number=number;
    }
    public long getNumber(){
        return this.number;
    }
}


再來示範繼承SQLiteOpenHelper的物件並建立資料庫與表格

package com.example.sqlite;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.database.sqlite.SQLiteOpenHelper;
public class MyDBHelper extends SQLiteOpenHelper {
    // 資料庫名稱
    public static final String DATABASE_NAME = "mydata.db";
    // 資料庫版本,資料結構改變的時候要更改這個數字,通常是加一
    public static int VERSION = 1;    
    // 資料庫物件,固定的欄位變數
    private static SQLiteDatabase database;
    //context為當前activity的上下文,name為要操作的資料庫名稱,factory用來做深入查詢用,version為版本
    public MyDBHelper(Context context, String name, CursorFactory factory, int version) {
        super(context, name, factory, version);
        // TODO Auto-generated constructor stub
    }
    //只有在資料庫不存在時,才會呼叫onCreate()建立資料庫
    @Override
    public void onCreate(SQLiteDatabase db) {
        // TODO Auto-generated method stub
        // 建立要存放資料的資料表格
        // 1. SQL語法不分大小寫
        // 2. 這裡大寫代表的是SQL標準語法, 小寫字是資料表/欄位的命名
        // 建立應用程式需要的表格
        db.execSQL(Test_Data.CREATE_TABLE);
    }
    //使用建構子時如果版本增加,便會呼叫onUpgrade()刪除舊的資料表與其內容,再重新呼叫onCreate()建立新的資料表
    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        // TODO Auto-generated method stub
        // 刪除原有的表格
        db.execSQL("DROP TABLE IF EXISTS " + Test_Data.TABLE_NAME);
        // 呼叫onCreate建立新版的表格
        onCreate(db);
    }
    // 需要資料庫的元件呼叫這個方法,這個方法在一般的應用都不需要修改
    public static SQLiteDatabase getDatabase(Context context) {
        if (database == null || !database.isOpen()) {
            database = new MyDBHelper(context, DATABASE_NAME, null, VERSION).getWritableDatabase();
        }
        return database;
    }
}


上面範例的Test_Data物件是寫來實作表單、實作資料庫物件、關閉資料庫、新增記錄、查詢記錄、更改記錄、刪除記錄、建立範例資料,以下為該範例:
package com.example.sqlite;
import java.util.ArrayList;
import java.util.List;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
// 資料功能類別
public class Test_Data {
    // 表格名稱    
    public static final String TABLE_NAME = "test_data";
    // 編號表格欄位名稱,固定不變
    public static final String KEY_ID = "_id";
    // 其它表格欄位名稱
    public static final String NAME_COLUMN = "name";
    public static final String CONTENT_COLUMN = "content";
    public static final String COLOR_COLUMN = "color";
    public static final String NUMBER_COLUMN = "number";
    // 使用上面宣告的變數建立表格的SQL指令
    public static final String CREATE_TABLE = 
        "CREATE TABLE " + TABLE_NAME + " (" +
        KEY_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " +
        NAME_COLUMN + " TEXT NOT NULL, " +
        CONTENT_COLUMN + " TEXT, " +
        COLOR_COLUMN + " INTEGER NOT NULL, " +
        NUMBER_COLUMN + " INTEGER NOT NULL)";
    // 資料庫物件    
    private SQLiteDatabase db;
    // 建構子,一般的應用都不需要修改
    public Test_Data(Context context){
        db = MyDBHelper.getDatabase(context);
    }
    // 關閉資料庫,一般的應用都不需要修改
    public void close() {
        db.close();
    }
    // 新增參數指定的物件
    public Item insert(Item item) {
        // 建立準備新增資料的ContentValues物件
        ContentValues cv = new ContentValues(); 
        // 加入ContentValues物件包裝的新增資料
        // 第一個參數是欄位名稱, 第二個參數是欄位的資料
        cv.put(NAME_COLUMN, item.getName());
        cv.put(CONTENT_COLUMN, item.getContent());
        cv.put(COLOR_COLUMN, item.getColor().parseColor());
        cv.put(NUMBER_COLUMN, item.getNumber());
        // 新增一筆資料並取得編號
        // 第一個參數是表格名稱
        // 第二個參數是沒有指定欄位值的預設值
        // 第三個參數是包裝新增資料的ContentValues物件
        long id = db.insert(TABLE_NAME, null, cv);
        // 設定編號
        item.setId(id);
        // 回傳結果
        return item;
    }
    // 修改參數指定的物件
    public boolean update(Item item) {
        // 建立準備修改資料的ContentValues物件
        ContentValues cv = new ContentValues();
        // 加入ContentValues物件包裝的修改資料
        // 第一個參數是欄位名稱, 第二個參數是欄位的資料        
        cv.put(NAME_COLUMN, item.getName());
        cv.put(CONTENT_COLUMN, item.getContent());
        cv.put(COLOR_COLUMN, item.getColor().parseColor());
        cv.put(NUMBER_COLUMN, item.getNumber());
        // 設定修改資料的條件為編號
        // 格式為「欄位名稱=資料」
        String where = KEY_ID + "=" + item.getId();
        // 執行修改資料並回傳修改的資料數量是否成功
        return db.update(TABLE_NAME, cv, where, null) > 0;
    }
    // 刪除參數指定編號的資料
    public boolean delete(long id){
        // 設定條件為編號,格式為「欄位名稱=資料」
        String where = KEY_ID + "=" + id;
        // 刪除指定編號資料並回傳刪除是否成功
        return db.delete(TABLE_NAME, where , null) > 0;
    }
    // 讀取所有記事資料
    public List<Item> getAll() {
        List<Item> result = new ArrayList<Item>();
        //游標指向該資料表
        Cursor cursor = db.query(TABLE_NAME, null, null, null, null, null, null, null);
        //將所有資料轉成Item並添加進List
        while (cursor.moveToNext()) {
            result.add(getRecord(cursor));
        }
        //關閉游標
        cursor.close();
        return result;
    }
    // 取得指定編號的資料物件
    public Item get(long id) {
        // 準備回傳結果用的物件
        Item item = null;
        // 使用編號為查詢條件
        String where = KEY_ID + "=" + id;
        // 執行查詢
        Cursor result = db.query(TABLE_NAME, null, where, null, null, null, null, null);
        // 如果有查詢結果
        if (result.moveToFirst()) {
            // 讀取包裝一筆資料的物件
            item = getRecord(result);
        }
        // 關閉Cursor物件
        result.close();
        // 回傳結果
        return item;
    }
    // 把游標Cursor取得的資料轉換成目前的資料包裝為物件
    public Item getRecord(Cursor cursor) {
        // 準備回傳結果用的物件
        Item result = new Item();
        result.setId(cursor.getLong(0));
        result.setName(cursor.getString(1));
        result.setContent(cursor.getString(2));
        result.setColor(getColors(cursor.getInt(3)));
        result.setNumber(cursor.getLong(4));
        return result;
    }
    //將顏色的int型態轉換成Colors物件(只能為內建的幾種選項)
    private Colors getColors(int color) {
        Colors result = Colors.LIGHTGREY;
        if (color == Colors.BLUE.parseColor()) {
            result = Colors.BLUE;
        }else if (color == Colors.PURPLE.parseColor()) {
            result = Colors.PURPLE;
        }else if (color == Colors.GREEN.parseColor()) {
            result = Colors.GREEN;
        }else if (color == Colors.ORANGE.parseColor()) {
            result = Colors.ORANGE;
        }else if (color == Colors.RED.parseColor()) {
            result = Colors.RED;
        }
        return result;
    }
    // 取得資料數量
    public int getCount() {
        int result = 0;
        Cursor cursor = db.rawQuery("SELECT COUNT(*) FROM " + TABLE_NAME, null);
        if (cursor.moveToNext()) {
            result = cursor.getInt(0);
        }
        return result;
    }
    // 建立範例資料
    public void sample() {
        Item item = new Item(0,"test 玩家1號",null, Colors.RED,1);
        Item item2 = new Item(0,"test 玩家2號","內文zxc", Colors.BLUE,2);
        Item item3 = new Item(0,"test 玩家3號","內文asd", Colors.GREEN,3);
        Item item4 = new Item(0,"test 玩家4號","內文qwe", Colors.ORANGE,4);
        insert(item);
        insert(item2);
        insert(item3);
        insert(item4);
    }
}


最後來寫個app使用以上物件,此範例僅時做資料庫物件後,添加範例資料並取得所有資料顯示出來,最後關閉資料庫:

package com.example.sqlite;
import java.util.List;
import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;
public class MainActivity extends Activity {
    TextView t01;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        t01=(TextView) this.findViewById(R.id.t01);
        // 建立資料庫物件
        Test_Data test=new Test_Data(MainActivity.this);
        // 如果資料庫是空的,就建立一些範例資料
        // 這是為了方便測試用的,完成應用程式以後可以拿掉
        if (test.getCount() == 0) {
            test.sample();
        }
        t01.setText("Test測試:\n");
        //取得資料數
        t01.append("目前資料庫裡有"+String.valueOf(test.getCount()).toString()+"筆資料\n");
        // 取得所有記事資料
        List<Item> items=test.getAll();
        for(Item i:items){
            t01.append("\n第"+String.valueOf(i.getId()).toString()+"筆聊天紀錄\n");
            t01.append("該玩家number為="+String.valueOf(i.getNumber()).toString()+"\n");
            t01.append("name為="+i.getName()+"\n");
            t01.append("content為="+i.getContent()+"\n");
            t01.append("文字color為="+i.getColor().getCode()+"\n");
        }
        test.close();
    }
}



新增記錄時,實做好Item後使用insert()添加,id部分隨便填,到時會自動依位置更改
修改記錄時,實做好Item後使用update()修改,id部分設為想修改的記錄id
如需刪除記錄則使用delete()刪除,參數為想刪除的記錄id
查詢可以分為指定id與所有記錄,還有查詢資料筆數
基本的功能都有了,剩下的就自行修改使用了


此連結為用Eclipse輸出的範例:

https://mega.nz/#!M0lC1YoT!bc5eKV77Jix54E5Xgqht99S1fdii-yTMcl7L8fRbf18




參考資料:

http://blog.kdchang.cc/2015/07/android-note-sql-sq...

http://www.aaronlife.com/teaching/uch_android_2015...

http://www.codedata.com.tw/mobile/android-tutorial...




arrow
arrow

    SIN 發表在 痞客邦 留言(1) 人氣()