Android資料庫,第一篇。

weixin_34075551發表於2017-06-28

前言

Android開發涉及到的資料庫採用的是輕量級的SQLite3,但是裡面的道道也是很深啊!今天主要就是處理一下資料庫升級的思路

任務

明白要怎樣資料庫升級,以及資料庫升級的注意事項。還有就是手把手教學!!!嘿嘿。

資料型別

SQLite的資料型別分為以下幾種:
null: 表示該值為NULL值。
integer: 無符號整型值。
real:浮點值。
text: 文字字串,儲存使用的編碼方式為UTF-8、UTF-16BE、UTF-16LE。
blob: 儲存Blob資料,該型別資料和輸入資料完全相同。

注意:
  • 布林資料型別:
    SQLite並沒有提供專門的布林儲存型別,取而代之的是儲存整型1表示true,0表示false
  • 日期和時間資料型別:
    和布林型別一樣,SQLite也同樣沒有提供專門的日期時間儲存型別,而是以TEXT、REAL和INTEGER型別分別不同的格式表示該型別,如:
    TEXT: "YYYY-MM-DD HH:MM:SS.SSS"
    REAL: 以Julian日期格式儲存
    INTEGER: 以Unix時間形式儲存資料值,即從1970-01-01 00:00:00到當前時間所流經的秒數。

建立資料庫

Android 不自動提供資料庫。在 Android 應用程式中使用 SQLite,必須自己建立資料庫,然後建立表、索引,填充資料。Android 提供了 SQLiteOpenHelper 幫助你建立一個資料庫,你只要繼承 SQLiteOpenHelper 類根據開發應用程式的需要,封裝建立和更新資料庫使用的邏輯就行了。

public class DataBaseHelper extends SQLiteOpenHelper {

    public static final String CREATE_BOOK = "create table Book (" +
            "id integer primary key autoincrement," +
            "author text," +
            "price real," +
            "pages integer," +
            "name text)";
    private static final String TAG = "DataBaseHelper";
    private Context mContext;

    /**
     *
     * @param context 上下文環境
     * @param name    資料庫的名稱
     * @param factory   一個可選的遊標工廠(通常是Null)
     * @param version   資料庫的版本號
     */
    public DataBaseHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
        super(context, name, factory, version);
        mContext = context;
    }

    /**
     * 注意:在資料庫第一次建立的時候會呼叫這個方法
     * @param sqLiteDatabase
     */
    @Override
    public void onCreate(SQLiteDatabase sqLiteDatabase) {
        sqLiteDatabase.execSQL(CREATE_BOOK);
        Log.e(TAG, "建立成功");
    }

    /**
     * 資料庫升級的時候會呼叫這個方法。
     * @param sqLiteDatabase
     * @param oldVersion  舊的版本號
     * @param newVersion   新的版本號 
     */
    @Override
    public void onUpgrade(SQLiteDatabase sqLiteDatabase, int oldVersion, int newVersion) {

    }
}


可以看到我們把建表語句定義成了一個字串常量,然後再onCreate()方法中又呼叫了SQLiteDatabase的execSQL()方法去執行這條建表語句,並且列印Log提示建立成功,這樣就可以保證在資料庫建立完成的同時還能成功建立Book表。
下面是建立的程式碼,佈局的程式碼自己寫一個就可以,就是放幾個按鈕就可以:


public class SQLiteActivity extends AppCompatActivity implements View.OnClickListener {

    private static final String TAG = "SQLiteActivity";
    Button button1, button2, button3;


    private DataBaseHelper dataBaseHelper;
    private SQLiteDatabase db;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_sqlite);
        dataBaseHelper = new DataBaseHelper(this, "BookStore.db", null, 1);//建庫的建構函式
        button1 = (Button) findViewById(R.id.button1);
        button2 = (Button) findViewById(R.id.button2);
        button3 = (Button) findViewById(R.id.button3);
        button1.setOnClickListener(this);
        button2.setOnClickListener(this);
        button3.setOnClickListener(this);
    }

    @Override
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.button1:
                db = dataBaseHelper.getWritableDatabase();//這才是真正的建資料庫
                break;
            case R.id.button2:
                break;
            case R.id.button3:
                break;
        }
    }
}
注意

執行上面的程式碼,但是不點選button1,會發現沒有資料庫。其實真正的建庫是dataBaseHelper.getWritableDatabase();這行程式碼,當執行這行程式碼,才會建庫,建庫的時候發現這個庫是沒有的,是新的庫才會呼叫onCreate()。就是建庫的時候也會建表。
怎樣檢視建庫是否成功呢???下面以studio自帶模擬器處理的。
1.可以用DDMS檢視裡面的File Explorer-->data/data/包名/databases/裡面是否有BookStore.db檔案。
2.利用adb工具,它存放在sdk的platform-tools目錄下,使用命令列最好配置到環境變數中,也可以到他所在的目錄去開啟它。
開啟命令列,輸入adb shell,就會進入到裝置的控制檯,如下圖所示

2013488-aaa79b2dc868f84a.png
1.png

注意#符號表示我們當前已經是超級使用者了,如果顯示的是$符號,表示當前只是普通使用者而已,這時還需要輸入su命令切換一下使用者身份才行。有了超級使用者許可權之後,我們能做的事情就很多了。
然後使用 cd命令進行到/data/data/包名/databases/目錄下,並使用ls命令檢視該目錄裡的檔案,如下圖所示:

2013488-2e56c4ab1a9d2ed8.png
2.png

這個目錄下出現了兩個資料庫檔案,一個是我們建立的BookStore.db,而另一個BookStore.db-journal則是為了讓資料庫支援事務而產生的臨時日誌檔案,通常情況下這個檔案的大小是0位元組。
下面我們需要藉助sqlite命令來開啟資料庫了,只需要輸入 sqlite3 BookStore.db就可以開啟資料庫了。我天。。好神奇!!!如下圖所示:

2013488-9aec063f8d684078.png
3.png

這樣資料庫就開啟了,現在就可以對這個資料庫進行管理了,我們要是到有哪些表,可以輸入.table命令,如下圖所示:

2013488-b8e34acc7d08c143.png
4.png

可以看到我們有兩張表,android_metadata表是每個資料庫都會自動生成的,不用管理它,而另一張表就是我們自己建的表。我們還可以使用.schema命令來檢視他們的建表語句,如下圖所示:

2013488-0f753b3c5fa72e60.png
5.png

新增資料

我們有了資料庫,所以開始向裡面放入資料吧。下面就是插入資料,程式碼如下:我們用第二個按鈕進行插入操作;

public class SQLiteActivity extends AppCompatActivity implements View.OnClickListener {

    private static final String TAG = "SQLiteActivity";
    Button button1, button2, button3;
    private DataBaseHelper dataBaseHelper;
    private SQLiteDatabase db;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_sqlite);
        dataBaseHelper = new DataBaseHelper(this, "BookStore.db", null, 1);//建庫的建構函式
        db = dataBaseHelper.getWritableDatabase();
        button1 = (Button) findViewById(R.id.button1);
        button2 = (Button) findViewById(R.id.button2);
        button3 = (Button) findViewById(R.id.button3);
        button1.setOnClickListener(this);
        button2.setOnClickListener(this);
        button3.setOnClickListener(this);
    }

    @Override
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.button1:
                break;
            case R.id.button2:
                //插入資料
                ContentValues values = new ContentValues();
                values.put("author", "AA");
                values.put("price", 67.9);
                values.put("pages", 400);
                values.put("name", "LOOK");
                long long1 = db.insert("book", null, values);
                Log.e(TAG, "第一次的長度" + long1);
                values.clear();
                values.put("author", "BB");
                values.put("price", 87.9);
                values.put("pages", 300);
                values.put("name", "LOVE");
                long long2 = db.insert("book", null, values);
                Log.e(TAG, "第二次的長度" + long2);
                break;
            case R.id.button3:
                break;
        }
    }
}

我們把SQLiteDatabase的初始化放在了onCreate()方法裡面,避免button2點選的時候出現,db忘記生成的問題。
點選按鈕會發現Log的列印。插入資料的時候不用漢語原因是檢視資料庫的時候會出現亂碼。
查詢表的指令是select * from 表名,查詢出的內容如下圖所示:

2013488-7e6c753b8798f319.png
6.png

顯示的是剛剛我們插入的兩條資料。
上面資料庫有了,資料也有了但是我們發現有卻少一個列表,比如缺少出版時間time。我們要通過資料庫的升級處理這個問題,並且原來的資料要保留。

資料庫升級

修改表定義
SQLite數庫對ALTER TABLE命令支援非常有限,只能在表末尾新增列,不能修改列定義,不能刪除已有的列。那麼如果要修改表呢?我們可以採用臨時表的辦法。具體來說有四步:
1.將現有表重新命名為臨時表;
2.建立新表;
3.將臨時表的資料匯入新表(注意處理修改的列);
4.刪除臨時表。
既然有了這個思路我們上程式碼:


public class DataBaseHelper extends SQLiteOpenHelper {

    public static final String CREATE_BOOK = "create table Book (" +
            "id integer primary key autoincrement," +
            "author text," +
            "price real," +
            "pages integer," +
            "name text)";
    //新增欄位的新表
    public static final String CREATE_BOOK_NEW = "create table Book (" +
            "id integer primary key autoincrement," +
            "author text," +
            "price real," +
            "pages integer," +
            "name text," +
            "country text)";


    private static final String TAG = "DataBaseHelper";
    private Context mContext;

    /**
     * @param context 上下文環境
     * @param name    資料庫的名稱
     * @param factory 一個可選的遊標工廠(通常是Null)
     * @param version 資料庫的版本號
     */
    public DataBaseHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
        super(context, name, factory, version);
        mContext = context;
    }

    /**
     * 注意:在資料庫第一次建立的時候會呼叫這個方法
     *
     * @param sqLiteDatabase
     */
    @Override
    public void onCreate(SQLiteDatabase sqLiteDatabase) {
        sqLiteDatabase.execSQL(CREATE_BOOK);
        Log.e(TAG, "建立成功");
    }

    /**
     * 資料庫升級的時候會呼叫這個方法。
     *
     * @param sqLiteDatabase
     * @param oldVersion     舊的版本號
     * @param newVersion     新的版本號
     */
    @Override
    public void onUpgrade(SQLiteDatabase sqLiteDatabase, int oldVersion, int newVersion) {
        switch (oldVersion) {
            case 1:
                sqLiteDatabase.execSQL("ALTER TABLE Book RENAME TO Book_temp");
                sqLiteDatabase.execSQL(CREATE_BOOK_NEW);
                sqLiteDatabase.execSQL("insert into Book(author, price, pages,name,country) "
                        + "select author, price,pages ,name, \"china\" from Book_temp");
//                sqLiteDatabase.execSQL("DROP TABLE Book_temp");

        }
    }
}

不要忘記在我們的Activity中的onCreate()方法中改為下面程式碼:最主要的是版本號是2。。

  dataBaseHelper = new DataBaseHelper(this, "BookStore.db", null, 2);//建庫的建構函式

注意:上面我們沒有刪除Book_temp表,如需要刪除直接刪除就可以了。
執行程式重新開啟cmd.exe,檢視我們有多少表,如下圖所示:

2013488-5d7b20df66fa3bc5.png
7.png

出現了Book_temp表,這就是我們重新命名的表。
怎樣檢視錶的資料結構呢??有下面的指令
pragma table_info(表名)
我們來看看Book的資料結構:

2013488-1b860ca9d665f461.png
8.png

我們來看看Book_temp的資料結構:

2013488-fe170172df548709.png
9.png

還需要看看是否成功的到了過去:如下圖所示

2013488-d29fc1e93d9a7a96.png
10.png

嗯,處理完成。可以成功的完成資料庫的升級了。

相關文章