Android的SQLite----重新認識Android(10)

AND_YOU_with_ME發表於2017-04-14
SQL基礎入門
SQLite名稱的由來
SQL:結構化查詢語言Structured Query Language
Lite:簡化的
-->SQLite:自包含(只有一個檔案),無伺服器,零配置,事務性SQL引擎。
 
安裝使用步驟
1.下載sqlite3.exe
2.將sqlit3.exe拷貝到c:/windows/system32目錄下
3.啟動命令列視窗
4.輸入命令sqlite3
使用SQLite
以 .  開頭的是sqlite3軟體特有的指令。
SQL語句不用.開頭,但以;結束。
開啟/建立 資料庫的2種方式:
1.dos下執行命令:sqlite3 mytest.db 啟動sqlite3 並且設定開發的資料庫檔案,如果不存在且建表了則會建立.
2.先執行sqlite3,進入後輸入 .open mytest.db   該檔案會放在命令列所在目錄下, 沒有該檔案時會自動建立, 即使未建立任何表.
 
Sqlite3常用命令(區分大小寫)
在sqlit>提示符下輸入:
.open mytest.db開啟資料庫  mytest.db資料庫名,一次只能開啟一個庫檔案
.tables顯示所有表
.schema tb_users顯示錶結構tb_users是表名.但這是顯示建立表的建表語句。與mysql有區別,並不是顯示錶結構。
.databases列出連線的資料庫(一個)
.exit退出本程式(退出提示符sqlite>的命令)
.quit退出本程式
.help顯示幫助
.read 檔名  :載入執行sql指令碼,例如my.sql
 
備註: SQL語句不區分大小寫,SQLite命令區分大小寫.
一.資料庫查詢語句:select
 
1. 查詢所有資料:
select * from 表名;
select * from exam_books;
 
2.按照一定的條件查詢:
select * from 表名 where 條件;
select * from exam_books where id<20;
 
sqlite> select * from tb_student;   查詢tb_student表中的所有資料
1|zhangsan|18|male
2|lisi|28|female
3|zhangsan|18|male
4|wangwu|25|female
sqlite> select * from tb_student where age<20;   查詢tb_student表中age<20的所有資料
1|zhangsan|18|male
3|zhangsan|18|male
sqlite> select * from tb_student where name='zhangsan';   查詢tb_student表中name欄位的值是"zhangsan"的所有資料
1|zhangsan|18|male
3|zhangsan|18|male
sqlite> select * from tb_student where sex='female';   查詢tb_student表中sex是"female"的所有資料
2|lisi|28|female
4|wangwu|25|female
sqlite> select * from tb_student where sex='female' and age>26;   查詢tb_student表中sex是"female",並且age>26的所有資料
2|lisi|28|female
3.範圍條件查詢:
select * from 表名 where 欄位 between  值1  and 值2 ;
select * from exam_books where id<20 and id>10;   不包括10,20,  (10,20)
select * from exam_books where id between 10 and 20; --包含端點, 即 id的取值範圍 [10,20]
select * from exam_books where addtime between '2011-03-17 00:00:00' and '2011-03-18 00:00:00';
 
4.模糊查詢:
select * from 表名 where 欄位 like '%條件%';    --%表示有0~多個未知字元
select * from exam_books where bookname like '%馬克思%';
select * from exam_books where bookname like '馬__';
(查詢書名中第一個字是“馬”,後面有兩個字)
 
5.複合查詢:
select * from 表名 where 條件 and 另一個條件;
select * from exam_questions  where coursecode = '03706' and chapterid = 2;
 
6.查詢個數:
select count(*) from 表名 where 條件;  --查詢有多少條 滿足指定條件 的記錄
select count(*) from exam_questions  where coursecode = '03706' and chapterid = 2;
select count(*) from tb_student where age>21;  查詢該表中有多少條age>21的記錄(資料)
7.查詢結果按順序排列:
正序、倒序(asc/desc
select * from 表名 where 條件 order by 欄位 desc/asc;
select * from exam_questions where coursecode = '03706' order by chapterid;  --不寫asc/desc 則預設按照升序排序
sqlite> select * from tb_student ;
1|zhangsan|18|male
2|lisi|28|female
3|zhangsan|18|male
4|wangwu|25|female
sqlite> select * from tb_student order by age;  查詢結果按照年齡的升序排序(不寫asc就預設是asc升序)
1|zhangsan|18|male
3|zhangsan|18|male
4|wangwu|25|female
2|lisi|28|female
sqlite> select * from tb_student order by age desc;    查詢結果按照年齡的降序排序
2|lisi|28|female
4|wangwu|25|female
1|zhangsan|18|male
3|zhangsan|18|male
8.按照limit查詢某個範圍內的資料:
SELECT  * FROM exam_questions  order by id asc  limit  0, 15;(代表查詢出的第一頁的資訊)從0下標開始,查詢出15條資料.
SELECT  * FROM exam_questions  order by id asc  limit 15, 15;(代表查詢出的第二頁的資訊)從15下標開始,查詢出15條資料.
【備註:】limit後面的兩個數字中:第一個代表偏移量(第幾條資料,從0下標開始),第二個代表每頁展示的數量(多少條資料)
 
 
二. 刪除資料:delete
delete from 表名 where 條件;
delete from exam_questions where id<2000;
delete from exam_questions where coursecode='00041' and chapterid=1;
sqlite> select _id,name,age from tb_student where age=43;
21|lisi|43
38|lisi|43
sqlite> delete from tb_student where _id=21;   刪除該表中_id是21的記錄(資料行)
sqlite> select _id,name,age from tb_student where age=43;  刪除後,_id=21的記錄就查詢不到了
38|lisi|43
 
三.插入新資料:insert
格式一:insert into 表名(欄位1,欄位2....) values(值1,值2....); 
insert into exam_weburl(webname , weburl , info , bigtypeid) values('人人網', 'renren.com' , '這個網站不錯' , 3);
insert into tb_student (name,age,sex) values('zhangsan',18,'male');   sql語句注意要以分號結尾
格式二:insert into 表名 values(值1,值2....);   -- 要向所有的欄位依次插入資料時的簡化寫法,要求值列表的個數,順序,內容跟資料庫中表的欄位(列)要一 一對應.
sqlite>insert into tb_student values(3,'zhangsan',18,'male');   對該表的每個列都指定值
四、更新(修改)資料:update
update 表名 set 欄位1=值1, 欄位2=值2 where 條件;
update exam_weburl set info='這個網站不太好' where id=73;
update exam_weburl set webname='人人2', weburl='www.renren.com' where id=73;
sqlite> select _id,name,age from tb_student where age=42;    只查詢_id,name,age欄位的資料,不查詢其他欄位.如果是select * from...則是查詢所有欄位.
21|zhangsan17|42
38|zhangsan17|42
sqlite> update tb_student set name='lisi',age=43 where age=42;    把age=42的記錄(資料行)中的name欄位的值更新為"lisi",age欄位的值更新為43
sqlite> select _id,name,age from tb_student where age=42;  查詢結果為空,因為原來age=42的記錄,其age被更新為43
sqlite> select _id,name,age from tb_student where age=43;
21|lisi|43
38|lisi|43
 
五、建立/刪除表的語句:Integer _id;
CREATE TABLE [if not exists] 表名 (_id INTEGER PRIMARY KEY AUTOINCREMENT , 欄位2 資料型別2, 欄位3 資料型別3...)
PRIMARY   KEY:主鍵,能夠唯一區分出一條記錄(即一行資料)的欄位(或欄位的組合),不能為null
AUTOINCREMENT :自增長
例如:CREATE TABLE if not exists tb_newwords (_id INTEGER PRIMARY KEY AUTOINCREMENT , words  , detail );
      DROP TABLE [if exists] 表名 ;
sqlite> CREATE TABLE if not exists tb_student(_id INTEGER PRIMARY KEY AUTOINCREMENT,name VARCHAR2,age INTEGER,sex VARCHAR2);
六、更新表結構的語句:
1、如需在表中新增列,請使用下列語法:
ALTER   TABLE table_name
ADD  column_name datatype
 
SQLite不支援刪除列,修改列的資料型別.
【備註:】
DDL (data define language)  資料定義語句 create,drop,alter
DML (data manipulate[mə'nɪpjʊleɪt操縱;操作]  language) 資料操縱語句 insert,delete,update,select
DCL  (data control language)資料控制語句 grant, revoke.
TCL(transaction controll language)  事務控制語句. commit/rollback
學習SQL的主要重心應該放在DML語句上,而DML語句中的重點應該是在select語句上。
CRUD:是指在做計算處理時的增加(C:Create  用Insert into關鍵字)、查詢(R:Retrieve  用 select關鍵字)(重新得到資料)、更新(U:Update)和刪除(D:Delete)幾個單詞的首字母簡寫。主要被用在描述資料庫的基本操作。
insert into 表名  (欄位1,欄位2....) values(值1,值2...);
insert into 表名 values(值1,值2....);  該表中有多少列,就要有多少個值
select 欄位1,欄位2 ,....  from  表名  [where 條件]  [order by 欄位名 asc|desc] [limit 起始下標,要查出的行數];
update 表名 set 要更新的欄位1=新值1,要更新的欄位2=新值2,.....  [where 條件];
delete from 表名 [where 條件];
SQLiteDatabase
一、SQLite:
(一)、簡介:
[應用內可訪問的資料]Android通過 SQLite 資料庫引擎來實現結構化資料的儲存。在一個app中,可以訪問本app建立的私有資料庫,在其他應用程式裡不能訪問。除非該資料庫是放在sd卡中.
[小而快]SQLite 資料庫是一種用C語言編寫的嵌入式資料庫,它是一個輕量級的資料庫,最初為嵌入式設計的。它是在一些基礎簡單的語句處理上要比oracle / mysql快很多,而且其對記憶體的要求很低,在記憶體中只需要幾百KB的儲存空間。這是Android中採用 SQLite 資料庫的主要原因。
SQLite 支援事務處理功能,Transaction
SQLite 處理速度比MySQL等著名的開源資料庫系統更快;它沒有伺服器程式。 
[跨平臺]SQLite 通過單個的檔案儲存資料庫,資料庫名即檔名。 該檔案是跨平臺的,可以自由複製
[API]JDBC會消耗太多系統資源,所以JDBC對於手機並不合適,因此Android提供了新的API來使用 SQLite 資料庫。
二、SQLiteDatabase類:
SQLiteDatabase等同於JDBC中Connection和Statement的結合體。
SQLiteDatabase既代表與資料庫的連線,又能用於執行sql語句操作。
(一)、操作 SQLite 資料庫的步驟:【重要
1、通過靜態方法建立 SQLiteDatabase 物件,它代表與資料庫的連線;
2、建立表(執行CREATE);
3、呼叫SQLiteDatabase 物件執行資料庫操作(執行DML);
4、對查詢後的結果集Cursor(遊標/游標)進行處理。
 
(二)、操作 SQLite 資料庫的步驟詳細講解:
1、建立 SQLite 資料庫物件:SQLiteDatabase物件代表一個資料庫。 SQLiteDatabase提供了幾個靜態方法來開啟一個檔案對應的資料庫。
1.開啟已存在的資料庫:  
static  SQLiteDatabase  openDatabase(String path
SQLiteDatabase.CursorFactory factory, int flags)
2.存在則開啟,否則建立:
static  SQLiteDatabase  openOrCreateDatabase(String path, SQLiteDatabase.CursorFactory factory)
【備註:】方法引數說明:
1)引數中的path代表著資料庫的路徑, 如果想要放在私有快取路徑(/data/data/應用程式包名/cache/) 裡面,則只需要傳入getCacheDir().getAbsolutePath()+File.separator+"student.db",  
File getCacheDir()方法是Activity的方法
如果要放在Sd卡中,則要提供絕對路徑.
2)factory代表著在建立Cursor物件時,使用的工廠類,傳null即可;
3)flags代表的是建立表時的一些許可權設定(SQLiteDatabase裡面的靜態常量),多個許可權之間用"|"分隔:
OPEN_READWRITE:代表以讀寫方式開啟資料庫(常量值為:0)
OPEN_READONLY :代表的是以只讀方式開啟資料庫(常量值為:1)
CREATE_IF_NECESSARY:當資料庫不存在時建立資料庫(0x10000000)
SQLiteDatabase.openOrCreateDatabase(path,null)//推薦寫法,等價於:
SQLiteDatabase.openDatabase(path,null, SQLiteDatabase.OPEN_READWRITE | SQLiteDatabase.CREATE_IF_NECESSARY)
【核心示例程式碼:】
//當資料庫存在時的開啟方式:
String path =getCacheDir().getAbsolutePath()+ File.separator + "android_manual.db";//訪問放在內部儲存快取目錄中的資料庫
SQLiteDatabase db =SQLiteDatabase.openDatabase(path, null,SQLiteDatabase.OPEN_READWRITE);//讀寫方式開啟
Cursor cursor = db.rawQuery("select * from android_basic order by id desc limit 0 , 15",null);//執行原始查詢語句,注意:在java程式碼中,sql語句不寫分號;
raw的意思是:原始,原生
//當資料庫不存在時的開啟方式:
String path = SDCardHelper.getSDCardBaseDir() + File.separator + "words.db";//SDCardHelper.getSDCardBaseDir()是自定義的工具類的靜態方法, 用於獲取SD卡的根目錄
SQLiteDatabase  db = SQLiteDatabase.openOrCreateDatabase(path, null);
//建立表 (如果不存在則建立,如果存在則不建立)
db.execSQL("create table if not exists tb_words (_id integer primary key autoincrement ,english , chinese)");//引數字串結尾不要寫分號";"
2、在資料庫中建立表
核心示例程式碼:
String path = SDCardHelper.getSDCardBaseDir() + File.separator + "qf"+ File.separator + "words.db";//如果中間還有路徑,需要在程式中提前建立出來
SQLiteDatabase  db = SQLiteDatabase.openOrCreateDatabase(path, null);
db.execSQL("create table tb_words (_id integer primary key autoincrement ,english , chinese)");//引數字串結尾不要寫分號";"
 
【備註:】SQLite的資料型別
其實SQLite是無型別Typelessness的。這意味著你可以儲存任何型別的資料到資料庫表的任何列中, 無論這列宣告的資料型別是什麼。對於SQLite來說對欄位不指定型別是完全可以的。如:create table dict(_id integer primary key autoincrement , word , detail);       
    注意:這裡一定要注意,SQLite資料庫只有在一種情況下是要求型別匹配的,當我們建表是如create table table1(id integer primary key AUTOINCREMENT),則該欄位必須存整數。
    雖然SQLite允許忽略資料型別, 但是仍然建議在你的Create Table語句中指定資料型別. 因為資料型別對於你和其他的程式設計師交流, 或者你準備換掉你的資料庫引擎時能起到一個提示或幫助的作用。
 
3、呼叫SQLiteDatabase 物件的方法執行資料庫操作:【重要
void execSQL(String sql) ;    執行不帶佔位符"?"的sql語句(update,insert,delete;  create表 ,drop表
void execSQL(String sql , Object[] args)    執行可帶佔位符"?"的sql語句(update,insert,delete;  create表 ,drop表).注意第二個引數必須傳物件陣列(例如Integer陣列),不能傳int陣列
Cursor rawQuery( String sql , String[] args )   執行可帶佔位符"?"的sql查詢(select語句) 任何型別的欄位(包括主鍵)都可以用"?"佔位,並用字串傳值;
Cursor遊標,游標.指向查詢結果中的一條記錄.
select _id,name,age,sex from tb_student where age>18 and sex='female' order by _id desc limit 5,15;
Cursor query(String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy, String limit)執行查詢功能
例如:query("tb_student",new String[]{"_id","name","age","sex","age>? and sex=?",new String[]{"18","female"},null,null,"_id desc","5,15"});
table: 表名;
columns:要查詢出來的欄位名;
selection:篩選條件,不寫where;
selectionArgs:篩選條件中的所有"?"的替代陣列;
orderBy:按什麼欄位來排序,如:想按照_id逆序排序(不要寫order by)  _id desc
limit:  偏移量,讀取數量   例如   0,10
不需要的引數 傳null
        對查詢結果進行操作:
當執行的是select語句,返回一個Cursor物件。Cursor類似於JDBC中的ResultSet結果集,預設指向第一條記錄之前,內建移動遊標等方法:
move(int offset)    按偏移量來移動
moveToFirst()   將記錄指標移動到第一行
moveToLast ()   將記錄指標移動到最後一行
moveToNext ()      將記錄指標移動到下一行  返回boolean
moveToPosition(int position)       將記錄指標移動到指定的一行
moveToPrevious()      將記錄指標移動到上一行
getColumnName(int index)    根據列的索引返回其相應的列名稱
getColumnIndex(String name)    根據列的名字返回其相應的索引
getColumnNames()       返回一個儲存有所有列名稱的字串陣列
getCount()    返回Cursor的行數(即查詢結果的行數)
getColumnCount()    返回列數
close()   關閉遊標結果集,釋放資源
getType(int columnIndex)    獲取指定下標欄位的資料型別。分別有0、1、2、3、4這幾個結果。
0: 代表null
1:代表int
2:代表float
3:代表String
4:代表blob

除了以上重要的幾個方法外,Android考慮到不熟悉sql語句的開發者,提供了進一步封裝後的一系列方法。這幾個方法引數眾多,平時不建議使用,但也要掌握,在ContentProvider中會有類似的方法,要注意區分。
【備註:】ContentValues的構建方式:
ContentValues c = new ContentValues();
c.put(String key,Xxx value);
下面方法是SQLiteDatabase中定義的:
long insert(String table, String nullColumnHack, ContentValues values);//第二個引數一般傳null
如果第二個引數傳null,第三個引數裡面必須有鍵值對資料;
如果第三個引數裡面沒有資料(只是想插入一個空行),第二個引數應隨便指定一個可以為null值的列名.
返回值為該行的id,返回-1表示插入失敗
int update(String table, ContentValuesvalues, String whereClause, String[] whereArgs)  
values:更新指定鍵的值
whereClause不寫where關鍵字
返回受該語句影響的行數
int delete(String table, String whereClause, String[] whereArgs)
返回受該語句影響的行數
 
在ListView中顯示使用者資訊,提示:
先建立資料庫,建立表,向使用者表中插入幾條記錄.
查詢資料庫中儲存的使用者資訊,組裝成List<MyUser>(包括_id,name,age等)並封裝到ArrayAdapter<MyUser>中.該陣列介面卡會把每個MyUser物件使用toString()方法 ,裝到每個條目中.
 
上面的案例也可以使用抽象類CursorAdapter及其子類SimpleCursorAdapter.
類似於new SimpleAdapter(Context  context,List<Map<String,Object>> data, int resource,String[ ] from, int [ ]to)
SimpleCursorAdapter是一種介面卡,用於資料庫的資料的適配.
  //構造方法格式: 
//SimpleCursorAdapter(Context context, int layout, Cursor c, String[ ] from, int[ ] to, int flags)
  CursorAdapter adapter = new SimpleCursorAdapter(
    this, 
    R.layout.item, 
    cursor, 
    new String[]{"_id","name","age"},
    new int[]{R.id.tv_id, R.id.tv_name, R.id.tv_age},
    CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);//如果資料來源發生變化則loader中可以更新
  (三)、事務
        資料庫事務(Database Transaction) ,是指作為單個邏輯工作單元執行的一系列操作,要麼完整地執行,要麼完全地不執行。事務的目的是為了保證資料的一致性。 預設情況下,insert/update/delete等操作都是單獨一個事務.不必手動開啟或結束事務.
 
例如:
設想網上購物的一次交易,其付款過程至少包括以下幾步資料庫操作:
一、更新客戶所購商品的庫存資訊
二、儲存客戶付款資訊--可能包括與銀行系統的互動
三、生成訂單並且儲存到資料庫中
四、更新使用者相關資訊,例如購物數量等等
正常的情況下,這些操作將順利進行,最終交易成功,與交易相關的所有資料庫資訊也成功地更新。但是,如果在這一系列過程中任何一個環節出了差錯,例如在更新商品庫存資訊時發生異常、該顧客銀行帳戶存款不足等,都將導致交易失敗。一旦交易失敗,資料庫中所有資訊都必須保持交易前的狀態不變,比如最後一步更新使用者資訊時失敗而導致交易失敗,那麼必須保證這筆失敗的交易不影響資料庫的狀態--庫存資訊沒有被更新、使用者也沒有付款,訂單也沒有生成。否則,資料庫的資訊將會一片混亂而不可預測。
資料庫事務正是用來保證這種情況下交易的平穩性和可預測性的技術
    db.beginTransaction();//開始事務
   try {
     ...需要同時完成的業務邏輯... 不是每次操作都必須寫的,只有"打包"幾個操作一起成功或失敗時才需要手動控制.     
   } finally {
     db.endTransaction();//提交事務
  }
 (四)、對SQLiteDatabase類進行封裝:
MySQLiteDatabaseHelper ( ) 構造方法,獲得一個資料庫連線物件
Cursor selectCursor(String sql, String[] selectionArgs) 執行帶佔位符的select語句,查詢資料,返回Cursor
int selectCount(String sql, String[] selectionArgs)執行帶佔位符的select語句,返回結果集的資料條數
boolean updateData(String sql, String[] bindArgs) 執行帶佔位符的update、insert、delete語句,create, drop,返回true或false
List<Map<String, Object>> cursorToList(Cursor cursor)作用:將cursor轉成list集合
    提示:利用getColumnNames();獲取全部列名,利用int getType(int columnIndex)    獲取指定下標欄位的資料型別
  0: 代表null ;1:代表int ; 2:代表float ; 3:代表String; 再根據資料型別, 利用getInt等方法從遊標中取值.
void closeDb()關閉資料庫連線
參考程式碼:
1、封裝MySQLiteDatabaseHelper 類核心程式碼:
public class MySQLiteDatabaseHelper {
    private String DBPath = Environment.getExternalStorageDirectory().getAbsolutePath();
    private String DBName = "android_manual.db";//資料庫名稱
    private SQLiteDatabase db;

    /**
     * @作用: 構造方法。目的是建立資料庫檔案、建立SQLiteDatabase例項。
     */
    public MySQLiteDatabaseHelper() {
        getConnection();//呼叫自定義的方法初始化資料庫連線
    }

    /**
     * @return void
     * @作用:獲得一個資料庫連線物件,即SQLiteDatabase物件。
     */
    public void getConnection() {
        db = SQLiteDatabase.openDatabase(DBPath + File.separator + DBName, null, SQLiteDatabase.OPEN_READWRITE);//第二個引數是工廠,固定傳入null
    }

    /**
     * @param sql
     * @param selectionArgs
     * @return Cursor
     * @作用:執行帶佔位符的select語句,查詢資料,返回Cursor
     */
    public Cursor selectCursor(String sql, String[] selectionArgs) {
        return db.rawQuery(sql, selectionArgs);
    }

    /**
     * @param sql
     * @param selectionArgs
     * @return int
     * @作用:執行帶佔位符的select語句,返回結果集的個數
     */
    public int selectCount(String sql, String[] selectionArgs) {
        Cursor cursor = db.rawQuery(sql, selectionArgs);
        int count = cursor.getCount();//結果集有多少條記錄
        cursor.close();
        return count;
    }

    /**
     * @param sql
     * @param bindArgs
     * @return boolean
     * @作用:執行帶佔位符的update、insert、delete語句,更新資料庫,返回true或false
     */
    public boolean updateData(String sql, String[] bindArgs) {
        try {
            db.execSQL(sql, bindArgs);//返回值型別為void
            return true;//沒出現異常,說明insert/update/delete成功
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    /**
     * @param sql
     * @param selectionArgs
     * @return List<Map<String, Object>>
     * @作用:執行帶佔位符的select語句,返回多條資料,放進List<Map<String,Object>>集合中。
     */
    public List<Map<String, Object>> selectData(String sql, String[] selectionArgs) {
        List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
        Cursor cursor = db.rawQuery(sql, selectionArgs);
        String[] cols_names = cursor.getColumnNames();//獲取每一個欄位的名字
        while (cursor.moveToNext()) {
            Map<String, Object> map = new HashMap<String, Object>();
            for (int i = 0; i < cols_names.length; i++) {
                String cols_value = cursor.getString(i);//每個下標都按照字串來獲取其欄位值
                map.put(cols_names[i], cols_value);//把每個欄位名和對應的值存到map中
            }
            list.add(map);
        }
        if (cursor != null) {
            cursor.close();
        }
        return list;
    }

    /**
     * 作用:將cursor轉成list集合
     *
     * @param cursor
     * @return List<Map<String, Object>>
     */
    public List<Map<String, Object>> cursorToList(Cursor cursor) {
        List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
        String[] cols_names = cursor.getColumnNames();
        while (cursor.moveToNext()) {
            Map<String, Object> map = new HashMap<String, Object>();
            for (int i = 0; i < cols_names.length; i++) {
                Object cols_value = null;
                switch (cursor.getType(i)) {//獲取指定下標的欄位的資料型別  1:int,  2:float,  3:String,  4:Blob,  0:null
                    case 1://int
                        cols_value = cursor.getInt(cursor.getColumnIndex(cols_names[i]));
                        break;
                    case 2://float
                        cols_value = cursor.getFloat(cursor.getColumnIndex(cols_names[i]));
                        break;
                    case 3://String
                        cols_value = cursor.getString(cursor.getColumnIndex(cols_names[i]));
                        break;
                    case 4://blob
                        cols_value = cursor.getBlob(cursor.getColumnIndex(cols_names[i]));
                        break;
                    default://0:null
                        cols_value = null;
                        break;
                }
                map.put(cols_names[i], cols_value);
            }
            list.add(map);
        }
        if (cursor != null) {
            cursor.close();
        }
        return list;
    }

    public void closeDb() {
        if (db != null) {
            db.close();
        }
    }
}


相關文章