Android中的SQLite使用學(xué)習(xí)
SQLite是非常流行的嵌入式關(guān)系型數(shù)據(jù)庫,輕載, 速度快,而且是開源。在Android中,runtime提供SQLite,所以我們可以使用SQLite,而且是全集的SQLite。SQLite提供 SQL接口,和一般的數(shù)據(jù)庫一樣。但是Android的API不采用JDBC,JDBC消耗太多的資源。
?
SQLite支持絕大部分SQL-92標(biāo)準(zhǔn),不支 持:FOREIGN KEY constraints, nested transactions, RIGHT OUTER JOIN, FULL OUTER JOIN, and some flavors of ALTER TABLE.而我們在手持終端上使用SQLite,一般并不涉及太復(fù)雜的數(shù)據(jù)庫處理,除了上訴,其他的SQL,包括tirger、transaction 等都是支持,應(yīng)該說SQLite提供的功能是足夠。
?
和一般的SQL數(shù)據(jù)庫比較,最大的差異是數(shù)據(jù)類 型,例如我們定義一個表的某個column的數(shù)據(jù)類型為INTEGET,如果在插入時這個數(shù)值采用String,在SQLite中是包會產(chǎn)生錯誤,我們可 以將定義表格的數(shù)據(jù)類型作為一個提示,用于說明期待的數(shù)據(jù)類型,但是并不真實起到檢測作用。如果真的需要限制,要以來程序的其他部分進(jìn)行判斷。
?
1、建立我們的數(shù)據(jù)庫
?
在MySQL等數(shù)據(jù)庫中,第一步是創(chuàng)建數(shù)據(jù)庫,第 二步是創(chuàng)建表,如需要,還加上我們的初始預(yù)制的數(shù)據(jù)。在Android的SQLite的使用是一樣的。稍微特別一點是,我們需要通過繼承 SQLiteOpenHelper這個類來達(dá)到目的。對于抽象類SQLiteOpenHelper的繼承,需要重 寫:1)constructor,2)onCreate()和onUpgrade(),下面舉例介紹。
?
這個例子,我們創(chuàng)建一個稱為bebook_db的數(shù)據(jù)庫,里面有一個叫mytable的表格,有三列:_id,Name,Weight。下面我們將演示如何創(chuàng)建數(shù)據(jù)庫,如何在數(shù)據(jù)庫中創(chuàng)建表,如何刪除表,如何更新數(shù)據(jù)庫。
?
/* 對于抽象類SQLiteOpenHelper的繼承,需要重寫:1)constructor,2)onCreate()和onUpgrade()? * */
public class Chapter22Db extends SQLiteOpenHelper{
?? ?public static final String DATABASE_BAME ="bebook_db";
?? ?/* step 1 :重寫構(gòu)造函數(shù)中,繼承super的構(gòu)造函數(shù),創(chuàng)建database */
??? public Chapter22Db(Context context){
?? ???? /* 第一個參數(shù) 為當(dāng)前環(huán)境
???????? * 第二個參數(shù) String name為數(shù)據(jù)庫文件,如果數(shù)據(jù)存放在內(nèi)存 ,則為null,
?? ????? * 第三個參數(shù) 為SQLiteDatabase.CursorFactory? factory,存放cursor,缺省設(shè)置為null
?? ? ? ? * 第四個參數(shù) 為int
version數(shù)據(jù)庫的版本,從1開始,如果版本舊,則通過onUpgrade()進(jìn)行更新,如果版本新則通過onDowngrade()進(jìn)行發(fā)布。例
如,我要更改mytable表格,增加一列,或者修改初始化的數(shù)據(jù),或者程序變得復(fù)雜,我需要增加一個表,這時我需要在版本的數(shù)字增加,在加載時,才會對
SQLite中的數(shù)據(jù)庫個更新,這點非常重要,同時參見onUpgrade()的說明 */
?? ??? ?super(context,DATABASE_BAME,null,1);
??? }
???
??
?/*step 2
:重寫onCreate(),如果Android系統(tǒng)中第一次創(chuàng)建我們的數(shù)據(jù)庫時(即后面介紹調(diào)用getWritableDatabase()或者
getReadbleDatabase()時),將調(diào)用onCreate(),這這里創(chuàng)建數(shù)據(jù)庫(雖然在構(gòu)造函數(shù)中填入數(shù)據(jù)庫名,但數(shù)據(jù)庫的創(chuàng)建實在
onCreate()中自動進(jìn)行。在這里一般進(jìn)行創(chuàng)建table和寫入初始數(shù)據(jù)*/
?? ?public void onCreate(SQLiteDatabase db) {
?? ???? //創(chuàng)建table:SQL的語句是“CREATE TABLE constants(_id INTEGER PRIMARY KEY AUTOINCREMENT,title TEXT, value REAL);”,我們可以直接通過db.execSQL(SQLCommand)來執(zhí)行沒有返回值的SQL語言,例如CREATE,DELETE,UPDATE,INSERT,DROP。
?? ???? db.execSQL("CREATE TABLE mytable(_id INTEGER PRIMARY KEY AUTOINCREMENT, Name TEXT,Weight REAL); ");
?? ????
?? ???? //下面是加入三個原始數(shù)據(jù),如果對表格進(jìn)行增、刪、改、查,后面會詳細(xì)介紹。下面的幾個數(shù)據(jù)來自Android自帶的重力表,據(jù)說是為了傳感器管理用,Android已經(jīng)考慮到我們在月球和火星上使用Android手機(jī)的情況^_^,程序員有時真的很無聊……
?? ??? ?ContentValues cv = new ContentValues();
?? ??? ?
?? ??? ?cv.put("Name", "Gravity, Earth");
?? ??? ?cv.put("Weight", SensorManager.GRAVITY_EARTH);
?? ??? ?db.insert("mytable", "Name", cv);
?? ??? ?
?? ??? ?cv.put("Name", "Gravity, Mars");
?? ??? ?cv.put("Weight", SensorManager.GRAVITY_MARS);
?? ??? ?db.insert("mytable", "Name", cv);
?? ??? ?cv.put("Name", "Gravity, Moon");
?? ??? ?cv.put("Weight", SensorManager.GRAVITY_MOON);
?? ??? ?db.insert("mytable", "Name", cv);
??? }
??? /* step 3:重寫onUpgrade(),如果版本比原來的高,將調(diào)用onUpgrade(),在這個例子中,我們刪除原來的表格,根據(jù)新需求創(chuàng)建*/
?? ?public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
?? ???? //這次同樣通過db.execSQL(SQLCommand)來執(zhí)行沒有返回值的SQL語言,將表格刪除
?? ??? ?db.execSQL("DROP TABLE IF EXISTS mytable");
?? ??? ?onCreate(db);
?? ?}
}
?
2、和數(shù)據(jù)庫進(jìn)行關(guān)聯(lián)
?
就如同在MYSQL中進(jìn)行來數(shù)據(jù)庫的創(chuàng)建,表格創(chuàng) 建和初始數(shù)據(jù)的填寫,其他的操作一般在Activity中和用戶互動產(chǎn)生?;貞浺幌挛覀冊贚inux環(huán)境中如何處理,首先是要創(chuàng)建和數(shù)據(jù)庫的連 接,Android也一樣,另外在Activity結(jié)束時,我們需要將連接斷開,以釋放有關(guān)資源。
?
public class Chapter22Test1 extends ListActivity{
?? ?private SQLiteDatabase? db = null;
?? ?private Cursor cursor = null; //在后面與ListView互動中使用
??? protected void onCreate(Bundle savedInstanceState) {
?? ???? super.onCreate(savedInstanceState);
?? ???? // 獲取處理SQLiteOpenHelper的子類的SQLite的實例,如果只讀,可以采用getReadableDatabase(),這個例子我們獎通過SQLiteDatabase實例的操作,來進(jìn)行對數(shù)據(jù)進(jìn)行增刪改查詢,采用可寫的方式。
?? ??? ?db= (new Chapter22Db (getApplicationContext())).getWritableDatabase();??
?? ?}
??? protected void onDestroy() {
?? ???? super.onDestroy();
?? ??? //釋放和數(shù)據(jù)庫的連接
?? ??? ?db.close();
?? ?}
}
?
3、對表格進(jìn)行操作
?
對表格的操作有兩種方式,一種是RAW方式,即直接給出SQL語句,另一種是采用SQLiteDatabase中給出的方法來進(jìn)行,姑且稱為API方式。下面就這兩種方式的增、刪、改、查進(jìn)行實驗。
?
3.1增加一行數(shù)據(jù)
?
在設(shè)置創(chuàng)建表格時,使用了db.execSQL(SQLCommand)來執(zhí)行沒有返回值的SQL語言,這個是RAW方式。另一種方式在之前加入原始數(shù)據(jù)時給出,通過db.insert("mytable","Name",<ContentValues values>);來實現(xiàn)。其中第二個參數(shù)比較特別。SQL是不運(yùn)行加入一個空的行。如果第二個參數(shù)不設(shè)置為null,則對這種情空行情況進(jìn)行處理,將對應(yīng)列的值設(shè)置為“NULL”。
?
//RAW方式。
db.execSQL("INSERT INTO mytable(Name,Weight) VALUES ('Test1',1.0);");
//API方式,通過db.insert("mytable","Name",<ContentValues values>);來處理,其中ContentValues是用于存儲名稱和數(shù)值,對應(yīng)為表格的列的名詞和其在行中的數(shù)據(jù)。
ContentValues values =new ContentValues(2);//ContentValues有兩個數(shù)值
values.put("Name", "Test2"); //一個列名為Name,數(shù)據(jù)為Test2
values.put("Weight", 2.0); //一個列名為Weight,數(shù)據(jù)為2.0
db.insert("mytable","Name",values);
?
3.2刪除一行數(shù)據(jù)
?
//RAW方式
db.execSQL("DELETE FROM mytable WHERE Name='Test1';");?? ?
//API方式,方法是:delete (String table, String whereClause, String[] whereArgs)
db.delete("mytable", "Name=?", {"Test1"});
?
3.3更新一行數(shù)據(jù)
?
//RAW方式
db.execSQL("UPDATE mytable SET Weight=5.0 WHERE Name='Test1';");
//API方式,方法是:update (String table, ContentValuesvalues, StringwhereClause, String[]whereArgs)
String[] name = {"Test1"};
ContentValues values =new ContentValues(2);
values.put("Name", "Test1");
values.put("Weight", 5.0);
db.update("mytable",values,"Name=?",name);
?
3.4查詢和游標(biāo)Cursor
?
上面的三個操作都是無返回值的,而查詢SELECT則不然,將返回游標(biāo)Cursor。下面是兩種方式的查詢
?
//RAW方式,帶返回值,采用db.rawQuery(SQL語句)方式
Cursor result1 =db.rawQuery("SELECT _id,Name,Weight from mytable ORDER BY Name", null);
/API
方式,帶返回值,采用public Cursor query (String table, String[] columns, String
selection, String[] selectionArgs, String groupBy, String having, String
orderBy)
String[] columns ={"Name","Weight"};
String[] name ={"Name"};
Cursor result2 = db.query("mytable", columns, "Name=?", name, null, null, null);
?
游標(biāo)和Iterator接口有些相似,對于Cursor result我們可以通過下面的方式來讀取數(shù)據(jù):
?
result.moveToFirst();
while(!result.isAfterLast()){
?? ?int id = result.getInt(0);
?? ?String name = result.getString(1);
?? ?double weight = result.getDouble(2);
?? ?System.out.println(" "+id + " ["+ name + "] " +weight);
?? ?result.moveToNext();
}?? ??? ?
result.close();????
通過Cursor我們可以讀取數(shù)據(jù)庫的詳細(xì)信息我 們可以數(shù)據(jù)用ArrayList<HashMap<>>來存放,由于real非對象,簡單地用 ArrayList<HashMap<String,String>>來存儲。我們已經(jīng)有能力對SQLite數(shù)據(jù)進(jìn)行處理,并也 有能力處理ListView,這樣可以編寫我們的Activity。
SQLite是非常流行的嵌入式關(guān)系型數(shù)據(jù)庫,輕載, 速度快,而且是開源。在Android中,runtime提供SQLite,所以我們可以使用SQLite,而且是全集的SQLite。SQLite提供 SQL接口,和一般的數(shù)據(jù)庫一樣。但是Android的API不采用JDBC,JDBC消耗太多的資源。
SQLite支持絕大部分SQL-92標(biāo)準(zhǔn),不支 持:FOREIGN KEY constraints, nested transactions, RIGHT OUTER JOIN, FULL OUTER JOIN, and some flavors of ALTER TABLE.而我們在手持終端上使用SQLite,一般并不涉及太復(fù)雜的數(shù)據(jù)庫處理,除了上訴,其他的SQL,包括tirger、transaction 等都是支持,應(yīng)該說SQLite提供的功能是足夠。
本文摘自 :https://blog.51cto.com/u