## 第八天.SQLite數據庫技術 ##
### 8.1 SQLite介紹 ###
#### 8.1.1數據庫存儲 ####
+ 在某些情況下,文件不是有效的
+ 多線程數據訪問
+ 需要事務處理
+ 如果應用程序處理可能變化的復雜數據結構
+ 數據庫對于創建它們的包套件是私有的
#### 8.1.2 SQLite介紹 ####
+ SQLite是一個輕量級的數據庫,體積大小只用幾千字節
+ 一些SQL的指令只是部分支持,例如:ALTER、TABLE
+ 廣泛應用在嵌入式移動設備之上。
+ 參閱http://www.sqlite.org 獲取更多信息
### 8.2 創建/打開/刪除數據庫 ###
#### 8.2.1 創建數據庫 ###
```
Context.createDatabase(
String name, //
int version, //
int mode, //
CursorFactory factory //
)
```
+ 創建一個新的數據庫并返回一個SQLiteDatabase對象
+ 數據庫不能被創建,則拋出FileNotFoundException異常
#### 8.2.2 其他創建數據庫的方法 ####
```
SQLiteDatabase mydataBase=SQLiteDatabase.create(new CursorFactory(){
//創建一個數據庫
//工廠類,一個可選工廠類,當查詢時調用來實例化一個光標
public Cursor newCursor(SQLiteDatabase db,
SQLiteCursorDriver masterQuery, String editTable,
SQLiteQuery query) {
return null;
}
});
SQLiteDatabase myDataBase=this.openOrCreateDatabase("myDataBase.db",
MODE_PRIVATE, new CursorFactory(){
//創建新的數據庫,名稱myDatabase,模式MODE_PRIVATE,游標工廠
//工廠類,一個可選工廠類,當查詢時調用來實例化一個光標
public Cursor newCursor(SQLiteDatabase db,
SQLiteCursorDriver masterQuery, String editTable,
SQLiteQuery query) {
return null;
}
});
```
#### 8.2.3 刪除數據庫 ####
+ Context.deleteDatabase(String name)
+ 刪除指定名稱的數據庫
+ 假如數據庫成功刪除則返回true,失敗則為false
#### 8.2.4 打開數據庫 ####
+ Context.openDatabase(String file,CursorFactory factory)
+ 打開一個存在的數據庫并返回一個SQLiteDatabase 對象
+ 如果數據庫不存在則拋出FileNotFoundException 異常
+ 如創建一個名為:myDataBase的數據庫,后綴為.db
```
SQLiteDatabase my_DataBase=
this.openOrCreateDatabase(
"myDateBase.db",
MODE_PRIVATE, null);
my_DataBase.close();//不要忘記關閉數據庫
```
#### 8.2.5 非查詢SQL 指令 ####
```
SQLiteDatabase.execSQL(String sql)
```
可以用來執行非查詢SQL指令,這些指令沒有結果, 包括:CREATE TABLE / DROP TABLE / INSERT 等等。
### 8.3 創建/刪除表 ###
#### 8.3.1 SQLite基礎案例 ####
```
private SQLiteDatabase mSQLiteDatabase=null;
// 打開已經存在的數據庫
mSQLiteDatabase = this.openOrCreateDatabase(DATABASE_NAME, MODE_PRIVATE, null);
/* 在數據庫mSQLiteDatabase中創建一個表 */
mSQLiteDatabase.execSQL(CREATE_TABLE);
/* 刪除數據庫 */
this.deleteDatabase(DATABASE_NAME);
/* 退出時,不要忘記關閉 */
mSQLiteDatabase.close();
/* 刪除一個表 */
mSQLiteDatabase.execSQL("DROP TABLE " + TABLE_NAME);
/* 更新一條數據 */
ContentValues cv = new ContentValues();
cv.put(TABLE_NUM, miCount);
cv.put(TABLE_DATA, "修改后的數據" + miCount);
mSQLiteDatabase.update(TABLE_NAME, cv, TABLE_NUM + "=" + Integer.toString(miCount - 1), null);
UpdataAdapter(); //更新界面
```
```
/* 向表中添加一條數據 */
ContentValues cv = new ContentValues();
cv.put(TABLE_NUM, miCount);
cv.put(TABLE_DATA, "測試數據庫數據" + miCount);
mSQLiteDatabase.insert(TABLE_NAME, null, cv);
miCount++;
UpdataAdapter(); //更新界面
/* 從表中刪除指定的一條數據 */
mSQLiteDatabase.execSQL("DELETE FROM " + TABLE_NAME + " WHERE _id=" + Integer.toString(miCount));
miCount--;
if (miCount < 0){
miCount = 0;
}
UpdataAdapter(); //更新界面
```
#### 8.3.2 SQLite基礎案例:更新視圖顯示 ####
```
/* 更新視圖顯示 */
public void UpdataAdapter(){
// 獲取數據庫Phones的Cursor
Cursor cur = mSQLiteDatabase.query(TABLE_NAME, new String[] { TABLE_ID, TABLE_NUM, TABLE_DATA }, null, null, null, null, null);
miCount = cur.getCount();
if (cur != null && cur.getCount() >= 0) {
// ListAdapter是ListView和后臺數據的橋梁
ListAdapter adapter = new SimpleCursorAdapter(this,
// 定義List中每一行的顯示模板
// 表示每一行包含兩個數據項
android.R.layout.simple_list_item_2,
// 數據庫的Cursor對象
cur,
// 從數據庫的TABLE_NUM和TABLE_DATA兩列中取數據
new String[] { TABLE_NUM, TABLE_DATA },
// 與NAME和NUMBER對應的Views
new int[] { android.R.id.text1, android.R.id.text2 });
/* 將adapter添加到m_ListView中 */
m_ListView.setAdapter(adapter);
} }
```
研究案例DatabaseDemo1
### 8.4 CRUD操作 ###
#### 8.4.1 查詢SQL 指令-游標Cursors ###
+ Android 使用游標(Cursors)來導航瀏覽查詢結果
+ 游標(Cursors)被android.database.Cursor 對象來描述
+ 一個游標(Cursors)是一個簡單的指針,它從查詢結果的一個元組跳到下一個元組(或前一個或第一個……)
+ 游標(Cursors)在它定位位置的那一刻返回元組數據
```
//為創建Cursor(游標),必須執行查詢,要么通過SQL使用rawQuery()方法
//或是更精心設計的方法,像query()方法
Cursor cur=my_DataBase.rawQuery("SELECT * FORM test", null);
if(cur!=null){//游標不為空
//返回給定名稱的列的基于0開始的index,如果該屬性列不存在則返回-1
//通過它們的index來檢索屬性值
int numColumn=cur.getColumnIndex("someNumber");
if(cur.moveToFirst()){
//cur.moveToFirst()讓游標指向第一行,如果游標指向第一行,則返回true
do {
int num=cur.getInt(numColumn);//獲得當前行該屬性的值
/*Cursor提供了不同的方法來回索不同的數據類型
例如getInt(int index)/getString(int index)等等*/
/*做一些事情*/
} while (cur.moveToNext());
/*游標移動到下一行,如果游標已經通過了結果集中的最后,
即沒有行可以移動時,則返回false*/
//其他可能移動的是previous() 和first()方法
}
}
```
### 5.5 事務處理 ###
#### 5.5.1 使用事務操作SQLite數據庫 ####
使用SQLiteDatabase的beginTransaction()方法可以開啟一個事務,程序執行到endTransaction() 方法時會檢查事務的標志是否為成功,如果為成功則提交事務,否則回滾事務。當應用需要提交事務,必須在程序執行到endTransaction()方法之前使用setTransactionSuccessful() 方法設置事務的標志為成功,如果不調用setTransactionSuccessful() 方法,默認會回滾事務。使用例子如下:
```
SQLiteDatabase db = ....;
db.beginTransaction();//開始事務
try {
db.execSQL("insert into person(name, age) values(?,?)", new Object[]{“lxt008", 4});
db.execSQL("update person set name=? where personid=?", new Object[]{“lxt008", 1});
db.setTransactionSuccessful();//調用此方法會在執行到endTransaction() 時提交當前事務,如果不調用此方法會回滾事務
} finally {
db.endTransaction();//由事務的標志決定是提交事務,還是回滾事務
}
db.close();
```
上面兩條SQL語句在同一個事務中執行。
**其他**
+ 數據庫輔助類
+ 研究案例DatabaseDemo2
+ 數據庫小工具
Sqlitebrowser可以簡單管理Sqlite數據庫
[示例下載](http://www.apkbus.com/android-83441-1-1.html)