<1>SQLite 介紹
SQLite 一個(gè)非常流行的嵌入式數(shù)據(jù)庫(kù),它支持 SQL 語(yǔ)言,并且只利用很少的內(nèi)存就有很好的性能。此外它還是開(kāi)源的,任何人都可以使用它。許多開(kāi)源項(xiàng)目((Mozilla, PHP, Python)都使用了 SQLite.
SQLite 由以下幾個(gè)組件組成:SQL 編譯器、內(nèi)核、后端以及附件。SQLite 通過(guò)利用虛擬機(jī)和虛擬數(shù)據(jù)庫(kù)引擎(VDBE),使調(diào)試、修改和擴(kuò)展 SQLite 的內(nèi)核變得更加方便
SQLite 基本上符合 SQL-92 標(biāo)準(zhǔn),和其他的主要 SQL 數(shù)據(jù)庫(kù)沒(méi)什么區(qū)別。它的優(yōu)點(diǎn)就是高效,Android 運(yùn)行時(shí)環(huán)境包含了完整的 SQLite。
SQLite 和其他數(shù)據(jù)庫(kù)最大的不同就是對(duì)數(shù)據(jù)類(lèi)型的支持,創(chuàng)建一個(gè)表時(shí),可以在 CREATE TABLE 語(yǔ)句中指定某列的數(shù)據(jù)類(lèi)型,但是你可以把任何數(shù)據(jù)類(lèi)型放入任何列中。當(dāng)某個(gè)值插入數(shù)據(jù)庫(kù)時(shí),SQLite 將檢查它的類(lèi)型。如果該類(lèi)型與關(guān)聯(lián)的列不匹配,則 SQLite 會(huì)嘗試將該值轉(zhuǎn)換成該列的類(lèi)型。如果不能轉(zhuǎn)換,則該值將作為其本身具有的類(lèi)型存儲(chǔ)。比如可以把一個(gè)字符串(String)放入 INTEGER 列。SQLite 稱(chēng)這為“弱類(lèi)型”(manifest typing.)。
此外,SQLite 不支持一些標(biāo)準(zhǔn)的 SQL 功能,特別是外鍵約束(FOREIGN KEY constrains),嵌套 transcaction 和 RIGHT OUTER JOIN 和 FULL OUTER JOIN, 還有一些 ALTER TABLE 功能。
除了上述功能外,SQLite 是一個(gè)完整的 SQL 系統(tǒng),擁有完整的觸發(fā)器,交易等等。
<2>Android 集成了 SQLite 數(shù)據(jù)庫(kù)
Android 在運(yùn)行時(shí)(run-time)集成了 SQLite,所以每個(gè) Android 應(yīng)用程序都可以使用 SQLite 數(shù)據(jù)庫(kù)。對(duì)于熟悉 SQL 的開(kāi)發(fā)人員來(lái)時(shí),在 Android 開(kāi)發(fā)中使用 SQLite 相當(dāng)簡(jiǎn)單。但是,由于 JDBC 會(huì)消耗太多的系統(tǒng)資源,所以 JDBC 對(duì)于手機(jī)這種內(nèi)存受限設(shè)備來(lái)說(shuō)并不合適。因此,Android 提供了一些新的 API 來(lái)使用 SQLite 數(shù)據(jù)庫(kù),Android 開(kāi)發(fā)中,程序員需要學(xué)使用這些 API。
數(shù)據(jù)庫(kù)存儲(chǔ)在 data/< 項(xiàng)目文件夾 >/databases/ 下。
<3>Android 開(kāi)發(fā)中使用 SQLite 數(shù)據(jù)庫(kù)
Activites 可以通過(guò) Content Provider 或者 Service 訪問(wèn)一個(gè)數(shù)據(jù)庫(kù)。下面會(huì)詳細(xì)講解如果創(chuàng)建數(shù)據(jù)庫(kù),添加數(shù)據(jù)和查詢(xún)數(shù)據(jù)庫(kù)。
Android 不自動(dòng)提供數(shù)據(jù)庫(kù)。在 Android 應(yīng)用程序中使用 SQLite,必須自己創(chuàng)建數(shù)據(jù)庫(kù),然后創(chuàng)建表、索引,填充數(shù)據(jù)。
*Android 提供了 SQLiteOpenHelper 幫助你創(chuàng)建一個(gè)數(shù)據(jù)庫(kù),你只要繼承 SQLiteOpenHelper 類(lèi),就可以輕松的創(chuàng)建數(shù)據(jù)庫(kù)。SQLiteOpenHelper 類(lèi)根據(jù)開(kāi)發(fā)應(yīng)用程序的需要,封裝了創(chuàng)建和更新數(shù)據(jù)庫(kù)使用的邏輯。SQLiteOpenHelper 的子類(lèi),至少需要實(shí)現(xiàn)三個(gè)方法:
- 構(gòu)造函數(shù),調(diào)用父類(lèi) SQLiteOpenHelper 的構(gòu)造函數(shù)。這個(gè)方法需要四個(gè)參數(shù):上下文環(huán)境(例如,一個(gè) Activity),數(shù)據(jù)庫(kù)名字,一個(gè)可選的游標(biāo)工廠(通常是 Null),一個(gè)代表你正在使用的數(shù)據(jù)庫(kù)模型版本的整數(shù)。
- onCreate()方法,它需要一個(gè) SQLiteDatabase 對(duì)象作為參數(shù),根據(jù)需要對(duì)這個(gè)對(duì)象填充表和初始化數(shù)據(jù)。
- onUpgrage() 方法,它需要三個(gè)參數(shù),一個(gè) SQLiteDatabase 對(duì)象,一個(gè)舊的版本號(hào)和一個(gè)新的版本號(hào),這樣你就可以清楚如何把一個(gè)數(shù)據(jù)庫(kù)從舊的模型轉(zhuǎn)變到新的模型。
接下來(lái)討論具體如何創(chuàng)建表、插入數(shù)據(jù)、刪除表等等。
調(diào)用 getReadableDatabase() 或 getWriteableDatabase() 方法,你可以得到 SQLiteDatabase 實(shí)例,具體調(diào)用那個(gè)方法,取決于你是否需要改變數(shù)據(jù)庫(kù)的內(nèi)容
為了創(chuàng)建表和索引,需要調(diào)用 SQLiteDatabase 的 execSQL() 方法來(lái)執(zhí)行 DDL 語(yǔ)句。如果沒(méi)有異常,這個(gè)方法沒(méi)有返回值。
<6>給表添加數(shù)據(jù)(Insert)
一種方法是使用 SQLiteDatabase 對(duì)象的 insert()。這些方法把 SQL 語(yǔ)句的一部分作為參數(shù)。示例如下:
<7>更新數(shù)據(jù)(update)
使用 SQLiteDatabase 對(duì)象的 update()。這些方法把 SQL 語(yǔ)句的一部分作為參數(shù)。示例如下:
類(lèi)似如SQL 中的DDL
update user set name = 'zhangsanfeng' where id = 1
<8>查詢(xún)數(shù)據(jù)(query)
使用 SQLiteDatabase 對(duì)象的 query()和游標(biāo)。
游標(biāo):
不管你如何執(zhí)行查詢(xún),都會(huì)返回一個(gè) Cursor,這是 Android 的 SQLite 數(shù)據(jù)庫(kù)游標(biāo),使用游標(biāo),你可以:
通過(guò)使用 getCount() 方法得到結(jié)果集中有多少記錄;
通過(guò) moveToFirst(), moveToNext(), 和 isAfterLast() 方法遍歷所有記錄;
通過(guò) getColumnNames() 得到字段名;
通過(guò) getColumnIndex() 轉(zhuǎn)換成字段號(hào);
通過(guò) getString(),getInt() 等方法得到給定字段當(dāng)前記錄的值;
通過(guò) requery() 方法重新執(zhí)行查詢(xún)得到游標(biāo);
通過(guò) close() 方法釋放游標(biāo)資源;
這些方法把 SQL 語(yǔ)句的一部分作為參數(shù)。示例如下:
第一個(gè)參數(shù)table:數(shù)據(jù)表的名稱(chēng)
String[] columns,而這個(gè)參數(shù)對(duì)應(yīng)的就是SQL語(yǔ)句中的“列名稱(chēng)”
where后面跟的字符串就是Android的method中對(duì)應(yīng)得參數(shù)String selection。Android的method中通常還有個(gè)參數(shù)與此相關(guān)就是 String[] selectionArgs,當(dāng)selection參數(shù)中包含問(wèn)號(hào)"?"時(shí),那么selectionArgs才會(huì)用到
String selection = ”City=?";
這時(shí)我們必須在selectionArgs中賦值 String[] selectionArgs = {"Beijing"};
也就是說(shuō)selectionArgs中的字符串就是對(duì)應(yīng)selection中的問(wèn)號(hào)所代表的變量。實(shí)際上就是讓selection中的過(guò)濾條件City可以動(dòng)態(tài)的賦值,而不是寫(xiě)死在程序當(dāng)中。在 query() 執(zhí)行時(shí)會(huì)對(duì) selectionArgs 中的字符串正確轉(zhuǎn)義并替換到對(duì)應(yīng)的 ? 處以構(gòu)成完整的 selection 字符串。 有點(diǎn)像 String.format()。
那么很顯然參數(shù)String groupBy就是對(duì)應(yīng)SQL語(yǔ)句中GROUP BY后面的字符串,GROUP BY是與合計(jì)函數(shù)(Aggregate Functions)如SUM()一起使用的。詳細(xì)的用法大家可以從網(wǎng)上查查。
參數(shù)String having對(duì)應(yīng)SQL語(yǔ)句HAVING后面的字符串,也是要與合計(jì)函數(shù)一起使用的。
參數(shù)String orderBy對(duì)應(yīng)SQL語(yǔ)句ORDER BY后面的字符串。
參數(shù)limit指明返回的rows的數(shù)量。