Android開發之SQLite資料庫詳解
Android開發之SQLite資料庫詳解
請尊重他人的勞動成果,轉載請註明出處:Android開發之SQLite資料庫詳解
http://blog.csdn.net/fengyuzhengfan/article/details/40194393
Android系統整合了一個輕量級的資料庫:SQLite, SQLite並不想成為像Oracle、MySQL那樣的專業資料庫。SQLite只是一個嵌入式的資料庫引擎,專門適用於資源有限的裝置上(如手機、PDA等)適量資料存取。
雖然SQLite支援絕大部分SQL92文法,也允許開發人員使用SQL語句操作資料庫中的資料,但SQLite並不像Orade、MySQL資料庫那樣需要安裝、啟動伺服器處理序,SQLite資料庫只是一個檔案。
從本質上來看,SQLite的操作方式只是一種更為便捷的檔案操作。後面我們會看到,當應用程式建立或開啟一個SQLite資料庫時,其實只是開啟一個檔案準備讀寫,因此有人說SQLite有點像Microsoft的Access (實際上SQLite功能要強大得多)。
1.SQLiteDatabase 簡介
Android提供了SQLiteDatabase 代表一個資料庫(底層就是一個資料庫檔案>,一旦應用程式獲得了代表指定資料庫的SQLiteDatabase 對象,接下來就可通過SQLiteDatabase 對象來管理、操作資料庫了。
2.開啟擷取建立SQLiteDatabase的方法:
1)staticSQLiteDatabase openDatabase(Stringpath,SQLiteDatabase .CursorFactory factory, intflags):開啟path檔案所代表的SQLite資料庫。
2)staticSQLiteDatabase openOrCreateDatabase(File file,SQLiteDatabase .CursorFactory factory):開啟或建立(如果不存在)file檔案所代表的SQLite資料庫。
3)staticSQLiteDatabase openOrCreateDatabase(String path,SQLiteDatabase .CursorFactory factory):開啟或建立(如果不存在)path檔案所代表的SQLite資料庫。
3.操作SQLiteDatabase 的方法主要有:
1)execSQL(Stringsql, Object[] bindArgs):執行帶預留位置的 SQL語句。
2)execSQL(String sql):執行 SQL語句。
3)insert(Stringtable, String nullColumnHack,ContentValues values):向執行表中插入資料。
4)update(Stringtable, ContentValues values, String whereClause, String[] whereArgs):吏新指定表中的特定資料。
5)delete(Stringtable, String whereClause, String[] whareArgs):刪除指定表中的特定資料。
6)Cursorquery(String table, String[]columns, String selection, String[] selection Args,String groupBy, String having,String orderBy):對執行資料表執行査詢。
7)Cursorquery(String table, String[] columns, String selection, String[] selectionArgs,String groupBy, String having, String orderBy, String limit}:對執行資料表執行査詢。Limit參數控制最多査詢幾條記錄(用於控制分頁的參數)。
8)Cursorquery(boolean distinct, String table, String[] columns, String selection,String[] selectionArgs, String groupBy, String having, String orderBy, String limit):對指定表執行査詢語句。其中第一個參數控制是否去除重複值。
9)rawQuery(Stringsql, String[] selectionArgs):執行帶預留位置的 SQL查詢。
10)beginTransaction():開始事務。
11)endTransaction():結束事務。
從上面的方法不難看出,其實SQLiteDatabase的作用有點類似於JDBC的Connection介面,但SQLiteDatabase提供的方法更多:比如insert、update、delete、query等方法,其實這些方法完全可通過執行SQL語句來完成,但Android考慮到部分開發人員對SQL文法不熟悉,所以提供這些方法協助開發人員以更簡單的方式來操作資料表的資料。
4.操作Cursor
上面査詢方法都是返回一個Cursor對象,Android中的Cursor類似幹JDBC的ResultSet, Cursor同樣提供了如下方法來移動査詢結果的記錄指標。
1)move(int offset):將記錄指標向上或向下移動指定的行數。offset為正數就向下移動;為負數就是向上移動。
2)booleanmoveToFirst():將記錄指標移動到第一行,如果移動成功則返回true。
3)booleanmoveToLast():將記錄指標移動到最後一行,如果移動成功則返回true。
4)booleanmoveToNext():將記錄指標移動到下一行,如果移動成功則返回true。
5)booleanmoveToPosition(int position):將記錄指標移動到指定的行,如果移動成功則返回true。
6)booleanmoveToPrevious():將記錄指標移動到上一行,如果移動成功則返回true。
—旦將記錄指標移動到指定行之後,接下來就可以調用Cursor的getXxx()方法擷取該行的指定列的資料。
其實如果大傢具有JDBC編程的經驗,完全可以把SQLiteDatabase當成JDBC :中Connection和Statement的混合體因為SQLiteDatabase 既代表了與資料庫的串連,也可直接用於執行SQL操作;而Android中Cursor則可當成ResultSet,而且Cursor提供了更多便捷的方法來操作結果集。
5.建立資料庫和表
前面已經講到,使用SQLiteDatabase的靜態方法即可開啟或建立資料庫,例如如下代碼:
SQLiteDatabase.openOrCreateDatabase(“/mnt/db/temp.db3”,null);
上面的代碼就用於開啟或建立一個SQLite資料庫,如果/mnt/db/目錄下的temp.db3檔案 (該檔案就是一個資料庫)存在,那麼程式就是開啟該資料庫:如果該檔案不存在,則上面的代碼將會在該目錄下建立temp.db3檔案(即對應於資料庫)。
上面的代碼中沒有指定SQLiteDatabase.CursorFactory參數,該參數是一個用於返回 Cursor的工廠,如果指定該參數為null,則意味著使用預設的工廠。
上面的代碼即可返回一個SQLiteDatabase對象,該對象的execSQL可執行任意的SQL語句。
通過如下代碼在程式中建立資料表:
//定義建表語句
create tabletb_news(
id integer primarykey autoincrement,
title varchar(100)not null,
content varchar(2000));
在程式中執行上面的代碼即可在資料庫中建立一個資料表。
6.使用SQL語句操作SQLite資料庫
正如前面提到的,SQLiteDatabase的execSQL方法可執行任意SQL語句,包括帶預留位置的SQL語句。但由於該方法沒有返回值,一般用於執行DDL語句或DML語句;如果需要執行査詢語句,則可調用SQLiteDatabase 的 rawQuery(String sql,String[] selectionArgs)方法。例如如下代碼可用於執行DML語句,
//執行插入語句
String sql ="insert into tb_news(title,content,publishDate)values(?,?,?)";
db.execSQL(sql,new Object[]{news.getTitle(),news.getContent(),news.getPublishDate()});
提示:SQLite允許把各種類型的資料儲存到任何類型欄位中,開發人員可以不用關心聲明該欄位所使用的資料類型。例如程式可以把字串類型的值存INTEGER類型的欄位中,也可以把數值類型的值存入布爾類型的欄位中……但有一種情況例外:定義為INTEGERPRIMARY KEY的欄位只能儲存64位整數,當向這種欄位儲存除整數以外的其他類型的資料時,SQLite會產生錯誤。
由於SQLite允許存入資料時忽略底層資料列實際的資料類型,因此在編寫建表語句時可以柯略資料列後面的型別宣告,例如如下SQL語句對於SQLite也是正確的。
create table my_test
(_id integer primary key autoincrement,
name,pwd)
7.使用Android資料庫操作的操作資料庫
Android的SQLiteDatabase 提供了 insert、upate、delete或 query 語句來操作資料庫。
1.使用insert方法插入記錄
SQLiteDatabase 的 insert方法的簽名為 longinsert (String table, String nullColumnHack, ContentValuesvalues),這個插入方法的參數說明如下。
table:代表想插入資料的表名。
nullColumnHack:代表強行插入null值的資料列的列名。
values:代表一行記錄的資料。
insert方法插入的一行記錄使用ComentValues存放,ContentValues類似於Map,它提供了 put其中key為資料列的列名,該方法用於存入資料、getAsXxx(String key)方法用於取出資料。
例如如下語句:
ContentValues values = new ContentValues();
values.put ("name” , “孫悟空”);
values.put(“age”, 500);
//返回新添記錄的行號,該行號是一個內部值,與主鍵1^1無關,發生銪誤返回一1
long rowid = db.insert("person_in”,null,values);
不管第三個參數是否包含資料,執行insert()方法總會添加一條記錄,如果第三個參數為空白,會添加一條除主鍵之外其他宇段值都為null的記錄。
insert()方法的底層實際上依然是通過構造insert SQL語句來進行插入的,因此它產生的 SQL語句總是形如下面的語句:
//ContentValue 裡 key-value對的數值決定了下面的key-value對.
insert into <表名>(key1,key 2...) values(valuel , value2 ...)
此時如果第三個參數為null或其中key-value對的數量為0,由於insert方法還會按此方式產生一條insert語句,此時的insert語句為:
insert into <表名>()values()
上面的SQL語句顯然有問題,為了滿足SQL文法的需要,insert語句必須給定一個列名,如:insert intoperson(name)values(null),這個name列名就由第二個參數來指定。由此可見,當ComentValues為null或它包含的key-value對的數量為()時,第二個參數就會起作用了。
一般來說,第二個參數指定的列名不應該是主鍵列的列名,也不應該是非空列的列名,否則強行往這些資料列插入nul會引發異常。
2.使用update方法更新記錄
SQLiteDatabase 的 update方法的簽名為update(String table, ContentValues values, String whereClause, String[]whereArs),這個更新方法的參數說明如下:
table:代表想更新資料的表名。
values:代表想更新的資料。
whereClause:滿足該whereClause子句的記錄將會被更新。
whereArgs:用於為whereClause子句傳入參數。
該方法返回受此update語句影響的記錄的條數。
執行個體:
ContentValues values=new ContentValues();
values.put("title", news.getTitle());
values.put("content", news.getContent());
db.update("tb_news", values, "id=?",new String[]{String.valueOf(news.getId())});
3.使用delete方法刪除記錄
SQLiteDatabase 的 delete方法的簽名為delete(String table , String whereClause, String[]whereArgs),這個刪除的參數說明如下。
table:代表想刪除資料的表名。
whereClause:滿足該whereClause子句的記錄將會被刪除。
whereArgs:用於為whereClause子句傳入參數。
該方法返回受此delete語句影響的記錄的條數。
執行個體:
db=helper.getWritableDatabase();
db.execSQL("delete from tb_news where id=?",new String[]{String.valueOf(newsId)});
使用query方法查詢記錄
SQLiteDatabase 的 query方法的簽名為 Cursorquery(boolean distinct, String table,String[]
columns, String selection, Stringl]selecrionArgs, String groupBy, String having. String orderBy, String limit),這個query方法的參數說明如下,
distinct:指定是否去除重複記錄,
table:執行査詢資料的表名。
columns:要査詢出來的列名。相當於select語句select關鍵字後面的部分s
selection:査詢條件子句,相當於select語句where關鍵字後面的部分,在條件子
句中允許使用預留位置。
selectionArgs:用於為selection子句中預留位置傳入參數值,值在數組中的位置與預留位置在語句中的位置必須一致,否則就會有異常。
groupBy:用於控制分組?相當於select語句group by關鍵字後面的部分
having:用於對分組進行過濾。相當於select語句having關鍵字後面的部分
orderBy:用於對記錄進行排序。相當於select語句order by關鍵字後面的部分,如:personid desc, age asc;
limit:用於進行分頁,相當於select語句limit關鍵字後面的部分。
執行個體:
/**
*擷取分頁資料
*@param currentPage當前頁碼
*@param pageSize每頁顯示的資料量
*@return
*/
public List getNewsByPage(int currentPage,int pageSize) {
db=helper.getReadableDatabase();
Listlist=newArrayList();
String start=String.valueOf((currentPage-1)*pageSize);
Cursor cursor=db.query(true,"tb_news",null,null,null,null,null,"id asc",start+","+String.valueOf(pageSize));
// Stringsql="select* from tb_news order by id asc limit ?,?";
// Cursorcursor=db.rawQuery(sql, new String[]{start,String.valueOf(pageSize)});
while(cursor.moveToNext()){
intid=cursor.getInt(cursor.getColumnIndex("id"));
Stringtitle=cursor.getString(cursor.getColumnIndex("title"));
Stringcontent=cursor.getString(cursor.getColumnIndex("content"));
StringdateString=cursor.getString(cursor.getColumnIndex("publishDate"));
Date publishDate=null;
try {
publishDate= Utils.convertStr2Date(dateString);
}catch (ParseException e) {
//TODO Auto-generated catch block
e.printStackTrace();
}
list.add(new News(id, title,content, publishDate));
}
return list;
}
8.事務
SQLiteDatabase中包含如下兩個方法來控制事務。
beginTransaction():開始事務。
endTransaction():結束事務。
除此之外,SQLileDatabase還提供了如下方法來判斷當前上下文是否處於事務環境中》
inTransaction():如果當前上下文處於事務中,則返回true:否則返回false。
當程式執行endTiansaction()方法時將會結束事務——那到底是提交事務呢,還是復原事務呢?這取決於SQLiteDatabase是否調用了 setTransactionSuccessful()方法來設定事務標誌, 如果程式事務執行中調用該方法設定了事務成功則提交事務,否則程式將會回滾事務。範例程式碼如下:
//交易處理
publicvoid tran(int id1,int id2,int des){
SQLiteDatabase db =helper.getWritableDatabase();
//按照這個文法格式寫事務
db.beginTransaction();//開始事務
try{
db.execSQL("update tb_news set account=account - ? whereid=?",new Integer[]{des,id1});
// inti = 1 / 0;
db.execSQL("update tb_news set account=account + ? whereid=?",new Integer[]{des,id2});
db.setTransactionSuccessful();//設定事務成功標誌
}finally{
db.endTransaction();//結束事務:看事務是否成功,如果則提交,如果失敗則復原
}
}
9.SQLiteOpenHelper
SQLiteOpenHelper是Android提供的一個管理資料庫的工具類,可用於管理資料庫的建立和版木更新。一般的用法是建立SQLiteOpenHelper的子類,並擴充它的onCreate (SQLiteDatabasedb)和 onUpgrade (SQLiteDatabasedb,intoldVersion,intnewVersion)方法。
SQLiteOpenHelper包含如下常用的方法。
synchronized SQLiteDatabase getReadableDatabase():以讀寫的方式開啟資料庫對應的SQLiteDatabase對象。
synchronized SQLiteDatabase getWritableDatabase():以寫的方式開啟資料庫對應的SQLiteDatabase 對象。
abstract void onCreate (SQLiteDatabase db):當第一次建立資料庫時回調該方法。
abstract void onUpgrade (SQLiteDatabase db, int oldVersion, int newVersion):當資料庫版本更新時回調該方法。
synchronized void close():關閉所有開啟的SQLiteDatabase。
從上面的方法介紹中不難看出,SQLiteOpenHelper提供了getReadableDatabase()、 getWritableDatabase()兩個方法用於開啟資料庫連接,並提供了close方法來關閉資料庫連接,而開發人員需要做的就是重寫它的兩個抽象方法。
onCreate (SQLiteDatabase db):
用於初次使用軟體時產生資料庫表,當調用SQLiteOpenHelper的 getWritableDatabase()或者 getReadableDalabase()方法擷取用於操作資料庫的SQLiteDatabase執行個體時,如果資料庫不存在,Android系統會自動產生一個資料庫,接著調用onCreateO方法,onCreateO方法在初次產生資料庫時才會被調用,在onCreateO方法裡可以產生資料庫表結構及添加一些應用使用到的初始化資料。
onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion):
用於升級軟體時更新資料庫表結構,方法在資料庫的版本發生變化時會被調用,該方法調用時oldVersion代表資料庫之前的版本號碼,newVersion代表當前資料庫當前的版本號碼。那麼在哪裡指定資料庫的版本號碼呢?當程式建立SQLiteOpenHelper對象時,必須指定一個version參數,該參數就決定了所使用的資料庫的版本——也就是說,資料庫的版本是由程式員控制的。只要某次建立 SQLiteOpenHdper時指定的資料庫版本號碼高於之前指定的版本號碼,系統就會自動觸發 onUpgrade(SQLiteDatabase db, int oldVersion, int new Version)方法,程式就可以在onUpgrade()方法裡面根據原版號和目標版本號碼進行判斷,即可根據版本號碼進行必需的表結構更新。
提示:實際上,當應用程式升級表結構時,完全可能因為已有的資料導致升級失敗,在這種時候程式可能需要先對資料進行轉姑,清空資料表中的記錄,接著對資料!表進行更新,當教據表更新完成後再將教據儲存回來。
一旦得到了SQLiteOpenHelper對象之後,程式無須使用SQLiteDatabase的靜態方法建立SQLiteDatabase 執行個體,而且可以使用getWritableDatabase()或 getReadableDatabase()方法來擷取一個用於操作資料庫的SQLiteDatabase執行個體。
其中getWritableDatabase()方法以讀寫方式開啟資料庫,一旦資料庫的磁碟空間滿了,資料庫就只能讀而不能寫,倘若使用getWritableDatabase()開啟資料庫就會出錯。 getReadableDatabase()方法先以讀寫方式開啟資料庫,如果資料庫的磁碟空間滿了,就會開啟失敗,當開啟失敗後會繼續嘗試以唯讀方式開啟資料庫。
請尊重他人的勞動成果,轉載請註明出處:Android開發之SQLite資料庫詳解
http://blog.csdn.net/fengyuzhengfan/article/details/40194393