GitHub項目地址:
https://github.com/Skymqq/DatabaseSave.git
SQLite是一款輕量級的關係型數據庫,它的運算速度非常快,佔用資源也很少,通常只需要幾百KB的內存就足夠了,因而特別適合在移動設備上使用。SQLite不僅支持標準的SQL語法,還遵循了數據庫的ACID事務,所以只要你以前使用過其他的關係型數據庫,就可以很快的上手SQLite。而SQLite又比一般的數據庫要簡單的多,它甚至不用設置用戶名和密碼就可以使用。Android正是把這個功能極爲強大的數據庫嵌入到了系統中,使用本地持久化的功能有了一次質的飛躍。
文件存儲和SharedPreferences存儲畢竟只適用於保存一些簡單的數據和鍵值對,當需要存儲大量複雜的關係型數據的時候,你就會發現這兩種存儲方式很難應付。比如我們手機的短信程序中可能會有很多個會話,每個會話中又包含了很多條信息內容,並且大部分會話還可能各自對應了電話薄中的某個聯繫人。很難想象如何用文件或者SharedPreferences來存儲這些數據量大、結構性複雜的數據吧?但是使用數據庫就可以做得到。那麼我們就趕快來看一看,Android中的SQLite數據庫到底是如何使用的。
創建數據庫
Android爲了讓我們能夠更加方便地管理數據庫,專門提供了一個SQLiteOpenHelper幫助類,藉助這個類就可以非常簡單地對數據庫進行創建和升級。既然有好東西可以直接使用,那麼我們當然要嘗試一下了,下面我就對SQLiteOpenHelper的基本用法進行介紹。
首先你要知道SQLiteOpenHelper是一個抽象類,這意味着如果我們想要使用它的話,就需要創建一個自己的幫助類去繼承它。SQLiteOpenHelper中有兩個抽象方法,分別是onCreate()和onUpgrade(),我們必須在自己的幫助類裏面重寫這兩個方法,然後分別在這兩個方法中去實現創建、升級數據庫的邏輯。
SQLiteOpenHelper中還有兩個非常重要的實例方法:getReadableDatabase()和getWritableDatabase()。這兩個方法都可以創建或打開一個現有的數據庫(如果數據庫已存在則直接打開,否則創建一個新的數據庫),並返回一個可對數據庫進行讀寫操作的對象。不同的是,當數據庫不可寫入的時候(如磁盤空間已滿),getReadableDatabase()方法返回的對象將以只讀的方式去打開數據庫,而getWritableDatabase()方法則將出現異常。
SQLiteOpenHelper中有兩個構造方法可供重寫,一般使用參數少一點的那個構造方法即可。這個構造方法中接收4個參數:
第一個參數是Context,這個沒什麼好說的,必須要有它才能對數據庫進行操作。
第二個參數是數據庫名,創建數據庫時使用的就是這裏指定的名稱。
第三個參數允許我們在查詢數據的時候返回一個自定義的Cursor,一般都是傳入null。
第四個參數表示當前數據庫的版本號,可用於對數據庫進行升級操作。
構建出SQLiteOpenHelper的實例之後,再調用它的getReadableDatabase()或getWritableDatabase()方法就能夠創建數據庫了,數據庫文件會存放在/data/data/<package name>/databases/目錄下。此時,重寫的onCreate()方法也會得到執行,所以通常會在這裏去處理一些創建表的邏輯。
接下來我們通過新建一個DatabaseSave項目來具體的瞭解SQLiteOpenHelper的使用吧。
這裏我們希望創建一個名爲BookStore.db的數據庫,然後在這個數據庫中新建一張Book表,表中有id(主鍵)、作者、價格、頁數和書名等列。創建數據庫表當然還是需要用建表語句的,這裏也是要考驗一下你的SQL基本功了,Book表的創建語句如下所示:
public static final String CREATE_BOOK = "create table Book(" +
"id integer primary key autoincrement," +
"author text," +
"price real," +
"pages integer," +
"name text)";
integer:整型
text:文本類型
real:浮點型
blob:二進制類型
primary key:主鍵
autoincrement:自增
SQLiteOpenHelper.java代碼:
package com.example.administrator.databasesave;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.widget.Toast;
public class MyDatabaseHelper extends SQLiteOpenHelper {
private Context context;
public static final String CREATE_BOOK = "create table Book(" +
"id integer primary key autoincrement," +
"author text," +
"price real," +
"pages integer," +
"name text)";
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, "create table successfully", Toast.LENGTH_SHORT).show();
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
}
可以看到,我們把建表語句定義成了一個字符常量,然後在onCreate()方法中又調用了SQLiteDatabase的execSQL()方法去執行這條建表語句,並彈出一條Toast提示表示創建成功,這樣就可以保證在數據庫創建完成的同時還能成功創建Book表。
activity_main.xml代碼:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<Button
android:id="@+id/btn_create"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Create Database"
android:textAllCaps="false"
android:textSize="18sp"
android:textStyle="bold" />
</LinearLayout>
MainActivity.java代碼:
package com.example.administrator.databasesave;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private Button btn_create;
private MyDatabaseHelper helper;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initData();
initView();//初始化UI控件
}
private void initData() {
helper=new MyDatabaseHelper(MainActivity.this,"BookStore.db",null,1);
}
private void initView() {
btn_create=(Button)findViewById(R.id.btn_create);
btn_create.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()){
case R.id.btn_create:
helper.getWritableDatabase();//以可寫的方式,創建或打開數據庫
break;
}
}
}
效果圖:
點擊Create Database按鈕之後彈出Toast提示,說明此時BookStore.db數據庫和Book表應該已經創建成功了,因爲當你再次點擊Create Database按鈕時,不會再有Toast彈出。可是我們怎麼才能證明它們確實是被創建成功了呢?如果還是使用Device File Explorer到data/data/com.example.administrator.databasesave/databases/路徑下看,如下所示:
生成了3個文件
1.BookStore.db:生成的BookStore數據庫文件
2.BookStore.db-shm :共享內存
3.BookStore.db-wal:write-ahead log,是保存的一個日誌文件
此時我們通過數據庫管理工具打開BookStore.db是看不到任何東西的,連表都看不到,我試了下。
所以這裏我在這裏介紹另外一種查看方式,通過adb shell來對數據庫和表的創建情況進行檢查。
adb是AndroidSDK中自帶的一個調試工具,使用這個工具可以直接對連接在電腦上的手機或模擬器進行調試操作。它存放在sdk的platform-tools目錄下,如果想要在命令行中使用這個工具,就需要先把它的路徑配置到環境變量裏。這裏我就暫不演示了,網上教程挺多也挺詳細的。
配置好了環境變量之後,就可以使用adb工具了,打開命令行界面。
步驟1:Windows+R 輸入 cmd 進入DOS命令行界面。
步驟2:輸入 adb shell 回車
步驟3:進入自己的項目路徑,如下圖所示:
cd /data/data/com.example.administrtor.databasesave/databases/是我的項目路徑
如果你也出現Permission denied,那麼你需要輸入一下su root命令來獲取root權限,然後就可以再操作一次了,如下所示:
步驟3:輸入cd /data/data/com.example.administrtor.databasesave/databases/
步驟4:輸入ls 回車之後我們會看到 BookStore.db BookStore.db-shm BookStore.db-wal 這3個文件就像我們在Device File Explorer中看到的一樣。
步驟5:輸入sqlite3 BookStore.db
步驟6:輸入 .table(注意前面有個點)
可以看到,此時數據庫中有兩張表,android_metadata表示每個數據庫中都會自動生成的,不用管它,而另外一張Book表就是我們剛剛點擊Create Database按鈕之後,通過MyDatabaseHelper所創建的。
步驟7:輸入.schema(注意前面有個點)
通過.shcema命令,我們可以看到創建表的sql語句,其中第二行的sql語句就是我們創建Book表的語句。
升級數據庫:
使用重寫的onUpgrade()方法來對數據庫進行升級,它在整個數據庫的管理工作當中起着非常重要的作用。
目前DatabaseSave項目中已經有一張Book表用於存放書的各種詳細數據,如果我們想再添加一張Category表用於記錄圖書的分類,該怎麼做呢?
比如Category表中有id(主鍵)、分類名和分類代碼這幾個列,那麼建表語句如下:
public static final String CREATE_CATEGORY = "create table Category(" +
"id integer primary key autoincrement," +
"category_name text," +
"category_code integer)";
MyDatabaseHelper.java代碼:
package com.example.administrator.databasesave;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.widget.Toast;
public class MyDatabaseHelper extends SQLiteOpenHelper {
private Context context;
public static final String CREATE_BOOK = "create table Book(" +
"id integer primary key autoincrement," +
"author text," +
"price real," +
"pages integer," +
"name text)";
public static final String CREATE_CATEGORY = "create table Category(" +
"id integer primary key autoincrement," +
"category_name text," +
"category_code integer)";
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);//執行sql語句創建Book表
db.execSQL(CREATE_CATEGORY);//執行sql語句創建Category表
Toast.makeText(context, "create table successfully", Toast.LENGTH_SHORT).show();
}
@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);
}
}
MainActivity.java代碼:
package com.example.administrator.databasesave;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private Button btn_create;
private MyDatabaseHelper helper;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initData();
initView();//初始化UI控件
}
private void initData() {
helper=new MyDatabaseHelper(MainActivity.this,"BookStore.db",null,2);
}
private void initView() {
btn_create=(Button)findViewById(R.id.btn_create);
btn_create.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()){
case R.id.btn_create:
helper.getWritableDatabase();//以可寫的方式,創建或打開數據庫
break;
}
}
}
注意:這裏在MainActivity.java中只將數據庫的版本號改爲2就行了。
運行效果:
爲了驗證一下Category表是不是已經創建成功了,我們在adb shell中打開BookStore.db數據庫,然後鍵入.table命令和.schema命令,如下所示:
步驟1:adb shell
步驟2:cd 項目路徑
步驟3:su root(如果出現Permission denied再輸入su root命令)
步驟4:cd 項目路徑
步驟5:sqlite3 BookStore.db
步驟6:.table
步驟7:.schema
C(Create)添加數據:
現在你已經掌握了創建和升級數據庫的方法,接下來就該學習一下如何對錶中的數據進行操作了。其實我們可以對數據進行的操作無非4中,即CRUD。
CRUD:
C(Create)添加
R(Retrieve)查詢
U(Update)更新
D(Delete)刪除
每一種操作又各自對應了一種SQL命令,如果你比較熟悉SQL語言的話,一定會知道
添加數據時使用insert
查詢數據時使用select
更新數據時使用update
刪除數據時使用delete
但是開發者的水平總是參差不齊的,未必每一個人都能非常熟悉地使用SQL語言,因此Android也提供了一系列的輔助性方法,使得Android中即使不去編寫SQL語句,也能輕鬆完成所有的CRUD操作。
前面我已經知道,調用SQLiteOpenHelper的getReadableDatabase()和getWritableDatabase()方法是可以用於創建和升級數據庫的,不僅如此,這兩個方法還都會返回一個SQLiteDatabase對象,藉助這個對象就可以對數據進行CRUD操作了。
那麼下面我們首先學習一下如何向數據庫的表中添加數據吧。SQLiteDatabase中提供了一個insert()方法,這個方法就是專門用於添加數據的。它接收3個參數,第一個參數是表名,我們希望向哪張表裏添加數據,這裏就傳入該表的名字。第二個參數用於在未指定添加數據的情況下給某些爲空的列自動賦值NULL,一般我們用不到這個功能,直接傳入null即可。第三個參數是一個ContentValues對象,它提供了一系列的put()方法重載,用於向ContentValues中添加數據,只需要將表中的每個列名以及相應的待添加數據傳入即可。
activity_main.xml代碼:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<Button
android:id="@+id/btn_create"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Create Database"
android:textAllCaps="false"
android:textSize="18sp"
android:textStyle="bold" />
<Button
android:id="@+id/btn_add"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Add Data"
android:textAllCaps="false"
android:textSize="18sp"
android:textStyle="bold" />
</LinearLayout>
MainActivity.java代碼:
package com.example.administrator.databasesave;
import android.content.ContentValues;
import android.database.sqlite.SQLiteDatabase;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private Button btn_create, btn_add;
private MyDatabaseHelper helper;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initData();
initView();//初始化UI控件
}
private void initData() {
helper = new MyDatabaseHelper(MainActivity.this, "BookStore.db", null, 2);
}
private void initView() {
btn_create = (Button) findViewById(R.id.btn_create);
btn_add = (Button) findViewById(R.id.btn_add);
btn_create.setOnClickListener(this);
btn_add.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_create:
helper.getWritableDatabase();//以可寫的方式,創建或打開數據庫
break;
case R.id.btn_add:
addData();//添加數據
Toast.makeText(this, "Add Data successfully", Toast.LENGTH_SHORT).show();
break;
}
}
private void addData() {
SQLiteDatabase db = helper.getWritableDatabase();
ContentValues cv = new ContentValues();
//開始組裝第一條數據
cv.put("name", "The Da Vinci Code");
cv.put("author", "Dan Brown");
cv.put("pages", 454);
cv.put("price", 16.96);
db.insert("Book", null, cv);
cv.clear();
//開始組裝第二條數據
cv.put("name", "The Lost Symbol");
cv.put("author", "Dan Brown");
cv.put("pages", 510);
cv.put("price", 19.95);
db.insert("Book", null, cv);
}
}
點擊Add Data按鈕之後,Toast提示數據已經添加成功,效果圖:
爲了證實數據已經成功添加,我們還是繼續使用adb shell來看一下BookStore.db數據庫中的Book表中的數據:
由此可見,我們向ContentValues容器中添加的兩組數據都成功地添加到了Book表中。
U(Update)更新數據
學習完了如何向表中添加數據,接下來我們看看怎樣才能修改表中已有的數據。SQLiteDatabase中提供了一個非常好用的updata()方法,用於對數據進行更新,這個方法接收4個參數,第一個參數和insert()方法一樣,也是表名,在這裏指定更新哪一張表 裏的數據。第二個參數是ContentValues對象,要把更新數據在這裏組裝進去。第三、第四個參數用於約束更新某一行或某幾行中的數據,不指定的話默認就是更新所有行。
activity_main.xml代碼:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<Button
android:id="@+id/btn_create"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Create Database"
android:textAllCaps="false"
android:textSize="18sp"
android:textStyle="bold" />
<Button
android:id="@+id/btn_add"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Add Data"
android:textAllCaps="false"
android:textSize="18sp"
android:textStyle="bold" />
<Button
android:id="@+id/btn_update"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Update Data"
android:textAllCaps="false"
android:textSize="18sp"
android:textStyle="bold" />
</LinearLayout>
MainActivity.java代碼:
package com.example.administrator.databasesave;
import android.content.ContentValues;
import android.database.sqlite.SQLiteDatabase;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private Button btn_create, btn_add, btn_update;
private MyDatabaseHelper helper;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initData();
initView();//初始化UI控件
}
private void initData() {
helper = new MyDatabaseHelper(MainActivity.this, "BookStore.db", null, 2);
}
private void initView() {
btn_create = (Button) findViewById(R.id.btn_create);
btn_add = (Button) findViewById(R.id.btn_add);
btn_update = (Button) findViewById(R.id.btn_update);
btn_create.setOnClickListener(this);
btn_add.setOnClickListener(this);
btn_update.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_create:
helper.getWritableDatabase();//以可寫的方式,創建或打開數據庫
break;
case R.id.btn_add:
addData();//添加數據
Toast.makeText(this, "Add Data successfully", Toast.LENGTH_SHORT).show();
break;
case R.id.btn_update:
updateData();//更新數據
Toast.makeText(this, "Update Data successfully", Toast.LENGTH_SHORT).show();
break;
}
}
private void addData() {
SQLiteDatabase db = helper.getWritableDatabase();
ContentValues cv = new ContentValues();
//開始組裝第一條數據
cv.put("name", "The Da Vinci Code");
cv.put("author", "Dan Brown");
cv.put("pages", 454);
cv.put("price", 16.96);
db.insert("Book", null, cv);
cv.clear();
//開始組裝第二條數據
cv.put("name", "The Lost Symbol");
cv.put("author", "Dan Brown");
cv.put("pages", 510);
cv.put("price", 19.95);
db.insert("Book", null, cv);
}
private void updateData() {
SQLiteDatabase db = helper.getWritableDatabase();
ContentValues cv = new ContentValues();
cv.put("price", 10.99);
db.update("Book", cv, "name=?", new String[]{"The Da Vinci Code"});
}
}
點擊Update Data按鈕之後,Toast提示數據已經更新成功,如下所示:
爲了證實數據已經成功更新,我們還是繼續使用adb shell來看一下BookStore.db數據庫中的Book表中的數據:
之前的數據:
更新之後的數據:
可以看到,我們將名字爲The Da Vinci Code的這本書的價格從16.96改成10.99。
D(Delete)刪除數據
前面我們學習了一下添加數據和更新數據,代碼不多,理解起來也很容易,刪除數據也很簡單,SQLiteDatabase中提供了一個delete()方法,專門用於刪除數據,這個方法接收了3個參數,第一個參數仍然是表名,用於刪除那張表中的數據,第二、第三個參數又是用於約束刪除某一行或某幾行的數據,不指定的話默認就是刪除所有行。
activity_main.xml代碼:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<Button
android:id="@+id/btn_create"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Create Database"
android:textAllCaps="false"
android:textSize="18sp"
android:textStyle="bold" />
<Button
android:id="@+id/btn_add"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Add Data"
android:textAllCaps="false"
android:textSize="18sp"
android:textStyle="bold" />
<Button
android:id="@+id/btn_update"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Update Data"
android:textAllCaps="false"
android:textSize="18sp"
android:textStyle="bold" />
<Button
android:id="@+id/btn_delete"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Delete Data"
android:textAllCaps="false"
android:textSize="18sp"
android:textStyle="bold" />
</LinearLayout>
MainActivity.java代碼:
package com.example.administrator.databasesave;
import android.content.ContentValues;
import android.database.sqlite.SQLiteDatabase;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private Button btn_create, btn_add, btn_update, btn_delete;
private MyDatabaseHelper helper;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initData();
initView();//初始化UI控件
}
private void initData() {
helper = new MyDatabaseHelper(MainActivity.this, "BookStore.db", null, 2);
}
private void initView() {
btn_create = (Button) findViewById(R.id.btn_create);
btn_add = (Button) findViewById(R.id.btn_add);
btn_update = (Button) findViewById(R.id.btn_update);
btn_delete = (Button) findViewById(R.id.btn_delete);
btn_create.setOnClickListener(this);
btn_add.setOnClickListener(this);
btn_update.setOnClickListener(this);
btn_delete.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_create:
helper.getWritableDatabase();//以可寫的方式,創建或打開數據庫
break;
case R.id.btn_add:
addData();//添加數據
Toast.makeText(this, "Add Data successfully", Toast.LENGTH_SHORT).show();
break;
case R.id.btn_update:
updateData();//更新數據
Toast.makeText(this, "Update Data successfully", Toast.LENGTH_SHORT).show();
break;
case R.id.btn_delete:
deleteData();//刪除數據
Toast.makeText(this, "Delete Data successfully", Toast.LENGTH_SHORT).show();
break;
}
}
private void addData() {
SQLiteDatabase db = helper.getWritableDatabase();
ContentValues cv = new ContentValues();
//開始組裝第一條數據
cv.put("name", "The Da Vinci Code");
cv.put("author", "Dan Brown");
cv.put("pages", 454);
cv.put("price", 16.96);
db.insert("Book", null, cv);
cv.clear();
//開始組裝第二條數據
cv.put("name", "The Lost Symbol");
cv.put("author", "Dan Brown");
cv.put("pages", 510);
cv.put("price", 19.95);
db.insert("Book", null, cv);
}
private void updateData() {
SQLiteDatabase db = helper.getWritableDatabase();
ContentValues cv = new ContentValues();
cv.put("price", 10.99);
db.update("Book", cv, "name=?", new String[]{"The Da Vinci Code"});
}
private void deleteData() {
SQLiteDatabase db = helper.getWritableDatabase();
db.delete("Book", "pages>?", new String[]{"500"});//刪除Book表中pages>500的這一行數據。
}
}
點擊Delete Data按鈕之後,Toast提示數據已經刪除成功,如下所示:
爲了證實數據已經成功刪除,我們還是繼續使用adb shell來看一下BookStore.db數據庫中的Book表中的數據:
之前的數據:
刪除之後的數據:
前後對比之後,我們發現Book表中pages>500的哪一行數據被成功地刪除了。
R(Retrieve)查詢數據
終於到了最後一種操作了,掌握了查詢數據方法之後,你就將數據庫的CRUD操作全部學完了。不過千萬不要因此而放鬆,因爲查詢數據是CRUD中最複雜的一種操作。
我們都知道SQL的全稱是Structured Query Language,翻譯成中文就是結構化查詢語言。它的大部分功能都體現在“查”這個字上的,而“增刪改”只是其中的一小部分功能。由於SQL查詢涉及的內容實在是太多了,因此在這裏我不準備對它展開來講解,而是隻會介紹Android上的查詢功能。如果你對SQL語言非常感興趣,可以專門找一本SQL的書進行學習。
相信你已經猜到了,SQLIteDatabase中還提供了一個query()方法用於對數據進行查詢。這個方法的參數非常複雜,最短的一個方法重載也需要傳入7個參數。那麼我們就先來看一下這7個參數的各自含義吧:
1.第一個參數:表名(表示我們希望從哪張表中查詢數據)
2.第二個參數:用於指定去查詢哪幾列,如果不指定則默認查詢所有列
3.第三個參數和第四個參數:用於約束查詢某一行或某幾行的數據,不指定則默認查詢所有行的數據
4.第五個參數:用於指定需要取group by的列,不指定則表示不對查詢結果進行group by操作。
5.第六個參數:用於對group by之後的數據進行進一步的過濾,不指定則表示不進行過濾
6.第七個參數:用於指定查詢結果的排序方式,不指定則表示使用默認的排序方式。
雖然query()方法的參數非常多,但是不要對它產生畏懼,因爲我們不必爲每條查詢語句都指定所有的參數,多數情況下只需要傳入少數幾個參數就可以完成查詢操作了。調用query()方法後會返回一Cursor對象,查詢到的所有數據都將從這個對象中取出。
activity_main.xml代碼:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<Button
android:id="@+id/btn_create"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Create Database"
android:textAllCaps="false"
android:textSize="18sp"
android:textStyle="bold" />
<Button
android:id="@+id/btn_add"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Add Data"
android:textAllCaps="false"
android:textSize="18sp"
android:textStyle="bold" />
<Button
android:id="@+id/btn_update"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Update Data"
android:textAllCaps="false"
android:textSize="18sp"
android:textStyle="bold" />
<Button
android:id="@+id/btn_delete"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Delete Data"
android:textAllCaps="false"
android:textSize="18sp"
android:textStyle="bold" />
<Button
android:id="@+id/btn_query"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Query Data"
android:textAllCaps="false"
android:textSize="18sp"
android:textStyle="bold" />
</LinearLayout>
MainActivity.java代碼:
package com.example.administrator.databasesave;
import android.content.ContentValues;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private Button btn_create, btn_add, btn_update, btn_delete, btn_query;
private MyDatabaseHelper helper;
public static final String TAG = "MainActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initData();
initView();//初始化UI控件
}
private void initData() {
helper = new MyDatabaseHelper(MainActivity.this, "BookStore.db", null, 2);
}
private void initView() {
btn_create = (Button) findViewById(R.id.btn_create);
btn_add = (Button) findViewById(R.id.btn_add);
btn_update = (Button) findViewById(R.id.btn_update);
btn_delete = (Button) findViewById(R.id.btn_delete);
btn_query = (Button) findViewById(R.id.btn_query);
btn_create.setOnClickListener(this);
btn_add.setOnClickListener(this);
btn_update.setOnClickListener(this);
btn_delete.setOnClickListener(this);
btn_query.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_create:
helper.getWritableDatabase();//以可寫的方式,創建或打開數據庫
break;
case R.id.btn_add:
addData();//添加數據
Toast.makeText(this, "Add Data successfully", Toast.LENGTH_SHORT).show();
break;
case R.id.btn_update:
updateData();//更新數據
Toast.makeText(this, "Update Data successfully", Toast.LENGTH_SHORT).show();
break;
case R.id.btn_delete:
deleteData();//刪除數據
Toast.makeText(this, "Delete Data successfully", Toast.LENGTH_SHORT).show();
break;
case R.id.btn_query:
queryData();//查詢數據
Toast.makeText(this, "Query Data successfully", Toast.LENGTH_SHORT).show();
break;
}
}
private void addData() {
SQLiteDatabase db = helper.getWritableDatabase();
ContentValues cv = new ContentValues();
//開始組裝第一條數據
cv.put("name", "The Da Vinci Code");
cv.put("author", "Dan Brown");
cv.put("pages", 454);
cv.put("price", 16.96);
db.insert("Book", null, cv);
cv.clear();
//開始組裝第二條數據
cv.put("name", "The Lost Symbol");
cv.put("author", "Dan Brown");
cv.put("pages", 510);
cv.put("price", 19.95);
db.insert("Book", null, cv);
}
private void updateData() {
SQLiteDatabase db = helper.getWritableDatabase();
ContentValues cv = new ContentValues();
cv.put("price", 10.99);
db.update("Book", cv, "name=?", new String[]{"The Da Vinci Code"});
}
private void deleteData() {
SQLiteDatabase db = helper.getWritableDatabase();
db.delete("Book", "pages>?", new String[]{"500"});//刪除Book表中pages>500的這一行數據。
}
private void queryData() {
SQLiteDatabase db = helper.getWritableDatabase();
//查詢Book表中的所有數據
Cursor cursor = db.query("Book", null, null, null, null, null, null);
if (cursor.moveToFirst()) {
do {
//遍歷Cursor對象,取出數據並打印
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.e(TAG, "name: " + name);
Log.e(TAG, "author: " + author);
Log.e(TAG, "pages: " + pages);
Log.e(TAG, "price: " + price);
} while (cursor.moveToNext());
}
cursor.close();
}
}
可以看到,我們首先在查詢按鈕的點擊事件裏面用一個queryData()方法將查詢的一系列操作給封裝了,在這個方法中我們通過調用SQLiteDatabase中的query()方法,然後只填了第一個參數,指定要查詢的數據庫表,也就是Book表。其餘的6個參數,我們都指定爲null了,這就表示希望查詢這張Book表中的所有數據,雖然這張表中目前只剩下一條數據了。查詢完之後就得到了一個Cursor對象,接着我們調用它的moveToFirst()方法將數據的指針移動到第一行的位置,然後進入了一個循環當中,去遍歷查詢到的每一行數據。在這個循環中可以通過Cursor的getColumnIndex()方法獲取到某一列在表中對應的位置索引,然後將這個索引傳入到相應的取值方法中,就可以得到從數據庫中讀取到的數據了。
點擊QueryData按鈕,Toast提示查詢數據成功,效果圖如下所示:
日誌打印Book表中所查詢出來的數據:
adb shell查詢BookStore.db數據庫、Book表中的數據: