前面兩篇文章Android數(shù)據(jù)存儲(chǔ)(一)和Android數(shù)據(jù)存儲(chǔ)(二)分別使用文件存儲(chǔ)薛训、SharedPreferences的方式來對(duì)數(shù)據(jù)進(jìn)行存儲(chǔ)终娃。這篇主要是講SQLite數(shù)據(jù)庫(kù)的創(chuàng)建获黔,表的創(chuàng)建勃蜘,以及數(shù)據(jù)的增刪改查罐氨。為了保持連貫性,我就把全部?jī)?nèi)容都在這篇文章中講了米间,所以內(nèi)容稍微有點(diǎn)長(zhǎng)强品。文中使用ADB工具來查看數(shù)據(jù)庫(kù)中的數(shù)據(jù),如果沒有安裝ADB調(diào)試工具的話屈糊,請(qǐng)自行安裝的榛。完整代碼在:https://github.com/AD-feiben/DatabaseTest
為什么要使用SQLite
文件存儲(chǔ)和SharedPreferences存儲(chǔ)只適用于去保存一些簡(jiǎn)單的數(shù)據(jù)和鍵值對(duì),當(dāng)需要存儲(chǔ)大量復(fù)雜的關(guān)系型數(shù)據(jù)的時(shí)候逻锐,這兩種存儲(chǔ)方式就很難應(yīng)付了夫晌。
1.創(chuàng)建數(shù)據(jù)庫(kù)
Android為了讓我們更加方便的管理數(shù)據(jù)庫(kù),專門提供了一個(gè)SQLiteOpenHelper幫助類昧诱,借助這個(gè)類可以非常簡(jiǎn)單地對(duì)數(shù)據(jù)庫(kù)進(jìn)行創(chuàng)建和升級(jí)晓淀。SQLiteOpenHelper是一個(gè)抽象類,我們要使用的話需要先創(chuàng)建一個(gè)自己的幫助類去繼承它鳄哭,而且必須在我們的幫助類重寫onCreate()和onUpgrade()這兩個(gè)方法要糊,然后分別在這兩個(gè)方法中去實(shí)現(xiàn)創(chuàng)建、升級(jí)數(shù)據(jù)庫(kù)的邏輯妆丘。
SQLiteOpenHelper有兩個(gè)非常重要的實(shí)例方法锄俄,getReadableDatabase()和getWritableDatabase()。這兩個(gè)方法都可以創(chuàng)建或者打開一個(gè)現(xiàn)有的數(shù)據(jù)庫(kù)勺拣,并返回一個(gè)可以數(shù)據(jù)庫(kù)進(jìn)行讀寫操作的對(duì)象奶赠。不同的是,當(dāng)數(shù)據(jù)庫(kù)不可寫入的時(shí)候(如磁盤空間已滿)getReadableDatabase()方法返回的對(duì)象將以只讀的方式去打開數(shù)據(jù)庫(kù)药有,而 getWritableDatabase()方法則將出現(xiàn)異常毅戈。
SQLiteOpenHelper有兩個(gè)構(gòu)造方法可以重寫,一般使用參數(shù)少一點(diǎn)的那個(gè)愤惰,這個(gè)構(gòu)造方法有四個(gè)參數(shù)苇经,第一個(gè)是Context,第二個(gè)是數(shù)據(jù)庫(kù)名宦言,第三個(gè)是允許我們?cè)诓樵償?shù)據(jù)的時(shí)候返回一個(gè)自定義的 Cursor扇单,一般傳入null,第四個(gè)表示當(dāng)前數(shù)據(jù)庫(kù)的版本號(hào)奠旺,用于升級(jí)數(shù)據(jù)庫(kù)蜘澜。實(shí)例化SQLiteOpenHelper對(duì)象后施流,調(diào)用它的getReadableDatabase()或getWritableDatabase()方法就能創(chuàng)建出數(shù)據(jù)庫(kù)了,數(shù)據(jù)庫(kù)文件存放于/data/data/<package name>/databases/目錄下鄙信。
在新建項(xiàng)目之前先來看一下SQL的建表語句
create table Book(id integer primary key autoincrement,name text,author text,pages integer,price real)
SQLite的數(shù)據(jù)類型比較簡(jiǎn)單瞪醋,integer表示整形,real表示浮點(diǎn)型装诡,text表示文本類型银受,blob表示二進(jìn)制類型。另外上述建表語句還使用primary key將id設(shè)為主鍵鸦采,autoincrement將id列設(shè)為自動(dòng)增長(zhǎng)的蚓土。
接下來新建一個(gè)DatabaseTest項(xiàng)目來看看如何闖創(chuàng)建數(shù)據(jù)庫(kù)吧。首先在布局中放一個(gè)Button用來創(chuàng)建數(shù)據(jù)庫(kù)赖淤,這部分就不展示出來了。然后創(chuàng)建MyDatabaseHelper類繼承自SQLiteOpenHelper谅河,代碼如下:
public class MyDatabaseHelper extends SQLiteOpenHelper {
private static final String CREATE_BOOK = "create table Book(" +
"id integer primary key autoincrement," +
"name text," +
"author text," +
"pages integer," +
"price real)";
private Context context;
public MyDatabaseHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
super(context, name, factory, version);
this.context = context;
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(CREATE_BOOK);
Toast.makeText(context, "Database Created succeeded", Toast.LENGTH_SHORT).show();
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
}
首先把建表語句定義為字符串常量咱旱,然后在onCreate()方法中調(diào)用SQLiteDatabase的execSQL()方法來執(zhí)行這條建表語句完成建表。然后在MainActivity的Button監(jiān)聽事件來完成數(shù)據(jù)庫(kù)的創(chuàng)建绷耍,findViewById和為Button設(shè)置鍵監(jiān)聽器的部分就不寫了吐限,代碼如下:
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private MyDatabaseHelper databaseHelper;
private SQLiteDatabase db;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
databaseHelper = new MyDatabaseHelper(this, "BookStore.db", null, 1);
……
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.create_database:
db = databaseHelper.getWritableDatabase();
break;
default:
break;
}
}
}
運(yùn)行一下程序,創(chuàng)建完數(shù)據(jù)庫(kù)之后就會(huì)彈出一個(gè)Toast來提醒褂始。接下來使用ADB來驗(yàn)證數(shù)據(jù)庫(kù)BookStore.db以及Book表的創(chuàng)建诸典。
然后用sqlite3 BookStore.db打開BookStore.db數(shù)據(jù)庫(kù)(注意數(shù)據(jù)庫(kù)名字不要打錯(cuò)了,如果你發(fā)現(xiàn)數(shù)據(jù)庫(kù)里沒有Book表必尼,很有可能就是你打錯(cuò)了數(shù)據(jù)庫(kù)的名字蒋搜,這個(gè)時(shí)候用.exit或者.quit命令就可以關(guān)閉這個(gè)錯(cuò)的數(shù)據(jù)庫(kù)了,再用rm 數(shù)據(jù)庫(kù)名就可以刪掉錯(cuò)誤的數(shù)據(jù)庫(kù)了)判莉。
然后用.table命令(注意“.”)就可以看到該數(shù)據(jù)庫(kù)下的表了豆挽。android_metadata 表是每個(gè)數(shù)據(jù)庫(kù)中都會(huì)自動(dòng)生成的,這個(gè)也不用管它券盅。這里還可以通過**.schema **命令來查看它們的建表語句帮哈。
2.在數(shù)據(jù)庫(kù)中新建一個(gè)表
如果要新建一個(gè)表的話,與前面的方法一樣渗饮,首先需要在MyDatabaseHelper類把建表語句定義為字符串常量但汞,然后在onCreate中完成建表宿刮。
public class MyDatabaseHelper extends SQLiteOpenHelper {
……
private static final String CREATE_CATEGORY = "create table Category(" +
"id integer primary key autoincrement," +
"category_name text," +
"category_cade integer)";
……
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(CREATE_BOOK);
db.execSQL(CREATE_CATEGORY);
Toast.makeText(context, "Database Created succeeded", Toast.LENGTH_SHORT).show();
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
}
重新運(yùn)行一下程序點(diǎn)擊Button可以發(fā)現(xiàn)并不會(huì)有Toast彈出來,用ADB工具也差看不到Category這張表私蕾。原因就在SQLiteOpenHelper的getWritableDatabase()只有數(shù)據(jù)庫(kù)不存在的時(shí)候才會(huì)創(chuàng)建數(shù)據(jù)庫(kù)并調(diào)用MyDatabaseHelper的onCreate方法僵缺,現(xiàn)在數(shù)據(jù)庫(kù)已經(jīng)存在,所以無論我們?cè)趺袋c(diǎn)“Create Database”都不會(huì)創(chuàng)建一個(gè)新的數(shù)據(jù)庫(kù)〔劝龋現(xiàn)在只有卸載這個(gè)程序或者利用ADB的rm BookStore.db命令將數(shù)據(jù)庫(kù)刪除后再創(chuàng)建新的數(shù)據(jù)庫(kù)才會(huì)有Category表磕潮。
以上兩種辦法都有點(diǎn)暴力,需要上線的APP肯定不能用這樣的方法容贝,有沒有其他的方法不這么暴力的呢自脯?答案肯定是有的,利用升級(jí)這個(gè)辦法我們就可以實(shí)現(xiàn)給數(shù)據(jù)庫(kù)添加一張新表或者其他的操作斤富。然后修改MyDatabaseHelper的onUpgrade方法膏潮。因?yàn)樯?jí)數(shù)據(jù)庫(kù)時(shí)就會(huì)調(diào)用這個(gè)方法。
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("drop table if exists Book");
db.execSQL("drop table if exists Category");
onCreate(db);
}
可以看到這里執(zhí)行了兩條drop語句满力,當(dāng)Book表或Category表已經(jīng)存在的話就會(huì)把這兩張表刪掉焕参,然后再調(diào)用onCreate()方法重新建表。只所以在重新建表之前要?jiǎng)h掉原來的表油额,是因?yàn)樵趧?chuàng)建表時(shí)如果已經(jīng)存在叠纷,那么就會(huì)直接報(bào)錯(cuò)。接下來修改MainActivity的代碼潦嘶。
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
……
@Override
protected void onCreate(Bundle savedInstanceState) {
……
databaseHelper = new MyDatabaseHelper(this, "BookStore.db", null, 2);
}
……
}
databaseHelper = new MyDatabaseHelper(this, "BookStore.db", null, 2)最后的版本號(hào)要比原來的版本號(hào)大涩嚣,數(shù)據(jù)庫(kù)才會(huì)進(jìn)行升級(jí)。重新運(yùn)行程序掂僵,再利用ADB工具來查看數(shù)據(jù)庫(kù)里的內(nèi)容航厚。
這次可以看到數(shù)據(jù)庫(kù)升級(jí)之后,Category表也被創(chuàng)建出來了】淳現(xiàn)在數(shù)據(jù)庫(kù)已經(jīng)創(chuàng)建出來了阶淘,也完成了升級(jí),但是Book表和Category表都沒有數(shù)據(jù)互妓,接下來就來看看怎么給Book表添加數(shù)據(jù)溪窒。
3.添加數(shù)據(jù)
通過前面的練習(xí),我們已經(jīng)知道冯勉,調(diào)用SQLiteOpenHelper的getReadableDatabase()或 getWritableDatabase()方法是可以用于創(chuàng)建和升級(jí)數(shù)據(jù)庫(kù)的澈蚌,不僅如此,這兩個(gè)方法還都會(huì)返回一個(gè)SQLiteDatabase對(duì)象灼狰,借助這個(gè)對(duì)象就可以對(duì)數(shù)據(jù)進(jìn)行 CRUD 操作了宛瞄。什么是CRUD操作?C就是Create(添加數(shù)據(jù))交胚;R就是Retrieve(查詢數(shù)據(jù))份汗;U就是Update(更新數(shù)據(jù))盈电;D就是Delete(刪除數(shù)據(jù))。
接下來就先來看看怎么進(jìn)行C操作吧杯活。SQLiteDatabase中提供了一個(gè)insert()方法匆帚,這個(gè)方法就是專門用于添加數(shù)據(jù)的。它接收三個(gè)參數(shù)旁钧,第一個(gè)參數(shù)是表名吸重,我們希望向哪張表里添加數(shù)據(jù),這里就傳入該表的名字歪今。第二個(gè)參數(shù)用于在未指定添加數(shù)據(jù)的情況下給某些可為空的列自動(dòng)賦值 null嚎幸,一般我們用不到這個(gè)功能, 直接傳入 null 即可寄猩。 第三個(gè)參數(shù)是一個(gè)ContentValues 對(duì)象嫉晶, 它提供了一系列的 put()方法重載,用于向ContentValues 中添加數(shù)據(jù)田篇,只需要將表中的每個(gè)列名以及相應(yīng)的待添加數(shù)據(jù)傳入即可车遂。
接下來再布局中加入一個(gè)Insert Data按鈕,在MainActivity中添加監(jiān)聽事件斯辰,代碼如下:
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
……
private ContentValues values = new ContentValues();
@Override
protected void onCreate(Bundle savedInstanceState) {
……
}
@Override
public void onClick(View v) {
switch (v.getId()) {
……
case R.id.insert_data:
db = databaseHelper.getWritableDatabase();
values.clear();
//第一條數(shù)據(jù)
values.put("name", "The Da Vinci Code");
values.put("author", "Dan Brown");
values.put("pages", 454);
values.put("price", 16.96);
db.insert("Book", null, values);
values.clear();
//第二條數(shù)據(jù)
values.put("name", "The Lost Symbol");
values.put("author", "Dan Brown");
values.put("pages", 510);
values.put("price", 19.95);
db.insert("Book", null, values);
break;
default:
break;
}
}
}
首先先實(shí)例化一個(gè)ContentValues對(duì)象,在insert數(shù)據(jù)之前先清空ContentValues的值坡疼,然后把要添加的數(shù)據(jù)放到ContentValues進(jìn)行組裝彬呻,這里并沒有給id那一列賦值,因?yàn)閕d我們已經(jīng)設(shè)置為自動(dòng)增長(zhǎng)的柄瑰,它的值會(huì)在入庫(kù)的時(shí)候自動(dòng)生成闸氮,所以不需要我們手動(dòng)賦值了,最后調(diào)用SQLiteDatabase的insert()方法將數(shù)據(jù)添加到對(duì)應(yīng)的表中教沾。這里實(shí)際上是添加了兩條數(shù)據(jù)蒲跨,因?yàn)檎{(diào)用了兩次insert()方法,并且ContentValues組裝的內(nèi)容也不相同授翻。
接下來運(yùn)行程序或悲,點(diǎn)擊Insert Data按鈕,再利用ADB工具查看效果堪唐。前面的命令都用過了就不過多解釋了巡语,select * from Book;是SQL命令,用來查詢表中的數(shù)據(jù)淮菠,完整的命令格式是“select列名稱from表名稱 where 限定條件”男公,可以選擇要查詢的列中滿足限定條件的數(shù)據(jù)。我們?cè)诹忻Q這里用*代替合陵,說明查詢所有列枢赔,而且不加限定條件就說明我們要查Book表的所有數(shù)據(jù)澄阳。
注意在最后要加上“;”,我就掉進(jìn)過這個(gè)坑中踏拜,好一會(huì)才爬出來碎赢。
可以看到數(shù)據(jù)已經(jīng)成功的條件到了Book表中了,接下來來看一下怎么進(jìn)行U操作吧执隧。
4.更新數(shù)據(jù)
SQLiteDatabase中也是提供了一個(gè)非常好用的update()方法用于對(duì)數(shù)據(jù)進(jìn)行更新揩抡,這個(gè)方法接收四個(gè)參數(shù),第一個(gè)參數(shù)和insert()方法一樣镀琉,也是表名峦嗤,在這里指定去更新哪張表里的數(shù)據(jù)。第二個(gè)參數(shù)是ContentValues對(duì)象屋摔,要把更新數(shù)據(jù)在這里組裝進(jìn)去烁设。第三、第四個(gè)參數(shù)用于去約束更新某一行或某幾行中的數(shù)據(jù)钓试,不指定的話默認(rèn)就是更新所有行装黑。
在布局中加入U(xiǎn)pdata data按鈕,在MainActivity中給它添加監(jiān)聽事件弓熏。
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
……
@Override
protected void onCreate(Bundle savedInstanceState) {
……
}
@Override
public void onClick(View v) {
switch (v.getId()) {
……
case R.id.update_data:
db = databaseHelper.getWritableDatabase();
values.clear();
values.put("price", 10.99);
db.update("Book", values, "name = ?", new String[]{"The Da Vinci Code"});
break;
default:
break;
}
}
}
這里還是使用同一個(gè)ContentValues恋谭,不過這次只放了一個(gè)price的數(shù)據(jù)。然后調(diào)用了SQLiteDatabase的update()方法去執(zhí)行具體的更新操作挽鞠,可以看到疚颊,這里使用了第三、第四個(gè)參數(shù)來指定具體更新哪幾行信认。第三個(gè)參數(shù)對(duì)應(yīng)的是SQL語句的where部分材义,表示去更新所有name等于?的行,而?是一個(gè)占位符嫁赏,可以通過第四個(gè)參數(shù)提供的一個(gè)字符串?dāng)?shù)組為第三個(gè)參數(shù)中的每個(gè)占位符指定相應(yīng)的內(nèi)容其掂。因此上述代碼想表達(dá)的意圖就是,將name為The Da Vinci Code的price改成10.99潦蝇。
運(yùn)行程序點(diǎn)擊Updata data按鈕款熬,通過ADB工具查看效果。
可以看到第一條數(shù)據(jù)也就是name為The Da Vinci Code的這條數(shù)據(jù)的price改為10.99了攘乒。數(shù)據(jù)的更新就到這里华烟,接下來看一下D操作吧。
5.刪除數(shù)據(jù)
刪除數(shù)據(jù)相比前面兩種操作就更加簡(jiǎn)單了持灰,SQLiteDatabase中提供了一個(gè)delete()方法專門用于刪除數(shù)據(jù)盔夜,這個(gè)方法接收三個(gè)參數(shù),第一個(gè)參數(shù)仍然是表名,第二喂链、第三個(gè)參數(shù)又是用于去約束刪除某一行或某幾行的數(shù)據(jù)返十,不指定的話默認(rèn)就是刪除所有行。
添加Delete data 按鈕椭微,然后為其添加監(jiān)聽事件洞坑。
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
……
@Override
protected void onCreate(Bundle savedInstanceState) {
……
}
@Override
public void onClick(View v) {
switch (v.getId()) {
……
case R.id.delete_data:
db = databaseHelper.getWritableDatabase();
db.delete("Book", "pages>?", new String[]{"500"});
break;
default:
break;
}
}
}
與更新數(shù)據(jù)一樣,這里也是使用了where來修飾要?jiǎng)h除的行蝇率,將第三個(gè)參數(shù)的值替換第二個(gè)參數(shù)的?占位符迟杂,代碼表達(dá)的意思就是刪除Book表中pages>500的那條數(shù)據(jù)。
運(yùn)行程序點(diǎn)擊Delete data 按鈕本慕,通過ADB工具查看效果排拷。
可以看到pages為510的這條數(shù)據(jù)被刪掉了,只剩下pages為454的這條數(shù)據(jù)锅尘。數(shù)據(jù)的刪除就到這里监氢,接下來看一下R操作吧。
6.查詢數(shù)據(jù)
SQL 的全稱是Structured Query Language藤违,翻譯成中文就是結(jié)構(gòu)化查詢語言浪腐。它的大部功能都是體現(xiàn)在“查”這個(gè)字上的,而“增刪改”只是其中的一小部分功能顿乒。
SQLiteDatabase中還提供了一個(gè)query()方法用于對(duì)數(shù)據(jù)進(jìn)行查詢议街,我將使用兩種查詢方法來做演示。這個(gè)方法的參數(shù)非常復(fù)雜璧榄,最短的一個(gè)方法重載也需要傳入七個(gè)參數(shù)傍睹。先來看一下這七個(gè)參數(shù)各自的含義吧。第一個(gè)參數(shù)不用說犹菱,當(dāng)然還是表名,表示我們希望從哪張表中查詢數(shù)據(jù)吮炕。第二個(gè)參數(shù)用于指定去查詢哪幾列腊脱,如果不指定則默認(rèn)查詢所有列。第三龙亲、第四個(gè)參數(shù)用于去約束查詢某一行或某幾行的數(shù)據(jù)陕凹,不指定則默認(rèn)是查詢所有行的數(shù)據(jù)。第五個(gè)參數(shù)用于指定需要去group by的列鳄炉,不指定則表示不對(duì)查詢結(jié)果進(jìn)行g(shù)roup by操作杜耙。第六個(gè)參數(shù)用于對(duì)group by之后的數(shù)據(jù)進(jìn)行進(jìn)一步的過濾,不指定則表示不進(jìn)行過濾拂盯。第七個(gè)參數(shù)用于指定查詢結(jié)果的排序方式佑女,不指定則表示使用默認(rèn)的排序方式。
第二種方法跟第一種差別不大,我就不這里贅述了团驱,直接在代碼中以注釋的方式來解釋每個(gè)參數(shù)摸吠。
首先添加Query data 按鈕,然后為其添加監(jiān)聽事件嚎花。
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
……
private String Tag = "MainActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
……
}
@Override
public void onClick(View v) {
switch (v.getId()) {
……
case R.id.query_data:
db = databaseHelper.getWritableDatabase();
/**
* 查詢指定表寸痢,返回一個(gè)Cursor對(duì)象。
* @param table 要查詢的表名紊选。
* @param columns 要查詢的列名啼止,如果傳入null將會(huì)查詢所有的列
* @param selection 指定Where的約束條件,用于約束查詢某一列或某幾列的數(shù)據(jù)兵罢,傳入空將會(huì)返回所有列献烦。
* @param selectionArgs 將selectionArgs值逐個(gè)替換selection中的"?"占位符。
* @param groupBy 控制列分組趣些,傳入null就不進(jìn)行分組
* @param having 對(duì)groupBy之后的數(shù)據(jù)進(jìn)一步過濾仿荆,傳入null則不進(jìn)行過濾
* @param orderBy 對(duì)查詢后的數(shù)據(jù)進(jìn)行排序,傳入null就會(huì)默認(rèn)排序坏平,也可能是無序的拢操。
* @return 返回一個(gè)Cursor對(duì)象
*/
Cursor cursor = db.query("Book", null, null, null, null, null, null);
/**
* @param distinct 傳入true就會(huì)去除重復(fù)的數(shù)據(jù),傳去false則反之舶替。
* @param table The table name to compile the query against.
* @param columns A list of which columns to return. Passing null will
* return all columns, which is discouraged to prevent reading
* data from storage that isn't going to be used.
* @param selection A filter declaring which rows to return, formatted as an
* SQL WHERE clause (excluding the WHERE itself). Passing null
* will return all rows for the given table.
* @param selectionArgs You may include ?s in selection, which will be
* replaced by the values from selectionArgs, in order that they
* appear in the selection. The values will be bound as Strings.
* @param groupBy A filter declaring how to group rows, formatted as an SQL
* GROUP BY clause (excluding the GROUP BY itself). Passing null
* will cause the rows to not be grouped.
* @param having A filter declare which row groups to include in the cursor,
* if row grouping is being used, formatted as an SQL HAVING
* clause (excluding the HAVING itself). Passing null will cause
* all row groups to be included, and is required when row
* grouping is not being used.
* @param orderBy How to order the rows, formatted as an SQL ORDER BY clause
* (excluding the ORDER BY itself). Passing null will use the
* default sort order, which may be unordered.
* @param limit 指明返回的rows的數(shù)量令境。
* @return A {@link Cursor} object, which is positioned before the first entry. Note that
* {@link Cursor}s are not synchronized, see the documentation for more details.
* @see Cursor
*/
// Cursor cursor = db.query(true,"Book",new String[]{"name","author","price"},"price<?",new String[]{"15"},null,null,null,null);
if (cursor.moveToFirst()) {
do {
String name = cursor.getString(cursor.getColumnIndex("name"));
String author = cursor.getString(cursor.getColumnIndex("author"));
int pages = cursor.getInt(cursor.getColumnIndex("pages"));
double price = cursor.getDouble(cursor.getColumnIndex("price"));
Log.d(Tag, "book name is " + name);
Log.d(Tag, "book author is " + author);
Log.d(Tag, "book pages is " + pages);
Log.d(Tag, "book price is " + price);
} while (cursor.moveToNext());
}
cursor.close();
break;
default:
break;
}
}
}
在這里我將兩種查詢數(shù)據(jù)的方法都寫在一起,這樣大家容易對(duì)比兩個(gè)方法有什么不同顾瞪,當(dāng)然查詢數(shù)據(jù)的方法不知這兩個(gè)舔庶,而且我給了這兩個(gè)方法的注釋,第一個(gè)方法用的是中文注釋(英文不好陈醒,有弄錯(cuò)的地方希望大神可以指正)惕橙,第二個(gè)方法我用的是源代碼中的注釋,但是有兩個(gè)參數(shù)是第一個(gè)方法中沒有的钉跷,我就用中文注釋了弥鹦。
先注釋掉第二個(gè)方法,來看看第一個(gè)查詢數(shù)據(jù)的結(jié)果是怎么樣的爷辙。在查詢按鈕的點(diǎn)擊事件里面調(diào)用了SQLiteDatabase的query()方法去查詢數(shù)據(jù)彬坏。這里的query()方法非常簡(jiǎn)單,只是使用了第一個(gè)參數(shù)指明去查詢Book表膝晾,后面的參數(shù)全部為null栓始。這就表示希望查詢這張表中的所有數(shù)據(jù),雖然這張表中目前只剩下一條數(shù)據(jù)了血当。查詢完之后就得到了一個(gè)Cursor對(duì)象幻赚,接著我們調(diào)用它的moveToFirst()方法將數(shù)據(jù)的指針移動(dòng)到第一行的位置禀忆,然后進(jìn)入了一個(gè)循環(huán)當(dāng)中,去遍歷查詢到的每一行數(shù)據(jù)坯屿。在這個(gè)循環(huán)中可以通過Cursor的getColumnIndex()方法獲取到某一列在表中對(duì)應(yīng)的位置索引油湖,然后將這個(gè)索引傳入到相應(yīng)的取值方法中,就可以得到從數(shù)據(jù)庫(kù)中讀取到的數(shù)據(jù)了领跛。接著我們使用Log的方式將取出的數(shù)據(jù)打印出來疙挺,借此來檢查一下讀取工作有沒有成功完成挚赊。最后別忘了調(diào)用close()方法來關(guān)閉Cursor。
現(xiàn)在我們的數(shù)據(jù)庫(kù)只有一條數(shù)據(jù),按下Insert data添加多兩條數(shù)據(jù)再按下Query data按鈕來查詢數(shù)據(jù)凭需,看Android Studio的控制臺(tái)輸出就可以知道查詢的結(jié)果了垒探。
不難看出一共是有3條數(shù)據(jù)徙鱼。我們?cè)儆肁DB工具來驗(yàn)證一下是不是3條數(shù)據(jù)复濒。
接下來看看第二種查詢方法會(huì)得出什么結(jié)果。首先注釋掉第一種方法兜粘,然后再取消注釋第二個(gè)方法申窘,重新run一下。再按下Query data按鈕孔轴,程序居然崩掉了剃法,看一下Log。
在Android中同樣可以使用SQL操作數(shù)據(jù)庫(kù)懂扼,例如:
如果文章對(duì)你有所幫助,那么請(qǐng)您點(diǎn)一下?
由于本人水平有限瑰妄,如有錯(cuò)誤陷嘴,歡迎大家指正。如果你在操作過程中發(fā)現(xiàn)一些沒有講到的錯(cuò)誤或者問題间坐,歡迎在評(píng)論留言灾挨,一起探討,共同學(xué)習(xí)進(jìn)步竹宋!