SQLite是一種嵌入式的數據庫引擎,最后是以文件的形式保存數據的,專門適用于資源有限的設備上進行適量的數據存儲,而Android全面支持標準的SQLite數據庫。
所有創建的SQLite數據庫,僅限于當前應用訪問,如果其他應用需要訪問,則必須提供的ContentProvider的支持,并且SQLite數據庫會隨著Android應用的卸載而被刪除。
從本質上來看,SQLite的操作方式只是一種更為便捷的文件操作,當應用程序創建或打開一個SQLite數據庫時,其實只是打開一個文件準備讀寫。
因為SQLite僅適用于資源有限的小型設備,所以本身就不應該把大量數據存儲在設備的SQLite數據庫里,SQLite只適合存儲一些小型的數據。
為了使SQLite和其他數據庫間的兼容性最大化,SQLite支持對列上類型進行“類型近似”,列的類型近似指的是存儲在列上的數據進行推薦類型存儲。所以雖然SQLite內部只支持null(空)、integer(整型)、real(浮點數)、text(文本)和blob(二進制)這五種數據類型,但實際上SQLite完全可以接受varchar(n)、char(n)、decimal(p, s)、date等類型數據,只不過SQLite會在運算或保存時將它們轉換為上面五種數據類型中相應的類型。大多數數據庫的引擎都是使用靜態的、強類型的數據類型,數據的類型是由它的容器決定的,這個容器是指被存放的特定列。而SQLite使用的是動態類型,在SQLite中,值的數據類型跟值本身相關,而不是與它的容器相關,所以SQLite允許把各種類型的數據保存到任何類型字段中,開發者可以不用關心聲明該字段說使用的數據類型。但是有一種情況例外,定義為integer primary key的字段只能存儲64位整數,當向這種字段保存除整數意外的其他類型的數據時,SQLite會產生錯誤。
SQLite數據庫文件存放位置
/data/data/<package name>/databases/
SQLite數據庫支持的數據類型
SQLite內部只支持null(空)、integer(整型)、real(浮點數)、text(文本)和blob(二進制)這五種數據類型。
SQLiteOpenHelper
SQLiteOpenHelper提供了兩個構造器,用于傳遞當前上下文對象以及SQLite數據庫版本信息,在SQLiteOpenHelper的繼承類的構造函數中會調用它,構造器的簽名如下:
SQLiteOpenHelper(Context context, String name,
SQLiteDatabase.CursorFactory factory, int version)
SQLiteOpenHelper(Context context, String name,
SQLiteDatabase.CursorFactroy factory, int version,
DatabaseErrorHandler errorHandler)
上面的構造函數中,都是用于創建一個SQLite數據庫,context為一個當前應用的上下文對象;name是數據庫名稱;factory是一個允許子類在查詢時使用的游標,一般不用(傳null即可);version是數據庫版本號;errorHandler是一個接口,傳遞當數據庫錯誤的時候,執行的補救方法。
在SQLiteOpenHelper中,可以進行SQLite數據庫的創建、維護、日志以及獲取可讀寫的數據庫對象,通過下面幾個常用方法得到支持:
1)String getDatabaseName():獲取數據庫名。
2)SQLiteDatabase getReadableDatabase():創建或者打開一個可讀的數據庫對象。
3)SQLiteDatabase getWritableDatabase():創建或者打開一個可讀/寫的數據庫對象。
4)abstract void onCreate(SQLiteDatabase db):當第一次調用SQLiteOpenHelper的時候執行,之后再次調用將不再執行,一般用于完成數據庫初始化的工作。
5)void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion):當數據庫版本號發生向上更新時被執行。
6)void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion):當數據庫版本號發生向下更新時被執行。
SQLiteDatabase
當使用SQLiteOpenHelper的getReadableDatabase()或者getWritableDatabase()方法獲取到SQLiteDatabase對象,就可以對這個數據庫進行操作了。
CRUD
其中C代表添加(Create),R代表查詢(Retrieve),U代表更新(Update),D代表刪除(Delete)。
1、使用SQL語句執行CRUD操作
1)插入數據
db.execSQL("insert into book (name, author, pages, price) values(?, ?, ?, ?)",
new String[] { "The Da Vinci Code", "Dan Brown", "454", "16.96" });
2)更新數據
db.execSQL("update book set price = ? where name = ?", new String[] { "10.99", "The Da Vinci Code" });
3)刪除數據
db.execSQL("delete from book where pages > ?", new String[] { "500" });
4)查找數據
db.rawQuery("select * from book", null);
void execSQL():通過SQL語句執行一條非查詢語句。
Cursor rawQuery():通過SQL語句執行一條查詢語句。
2、使用SQLiteDatabase所提供的方法實現CRUD操作
1)插入一條數據
long insert(String table, String nullColumnHack, ContentValues values)
table是表名;nullColumnHack用于在未指定添加數據的情況下給某些可為空的列自動賦值null,一般用不到這個功能,直接傳入null即可;values是一個 ContentValues對象,它提供了一系列的put()方法重載,用于向ContentValues中添加數據,只需要將表中的每個列名以及相應的待添加數據傳入即可。
2)根據條件,刪除數據。
int delete(String table, String whereCaluse, String[] whereArgs)
table是表名;whereCaluse和whereArgs用于去約束刪除某一行或某幾行的數據,不指定的話默認就是刪除所有行。
3)根據條件,更新數據。
int updata(String table,ContentValues values,String whereCaluse,String[] whereArgs)
table是表名;values是ContentValues對象要把更新數據在這里組裝進去;whereCaluse和whereArgs用于去約束更新某一行或某幾行中的數據,不指定的話默認就是更新所有行。
4)根據條件,查詢數據。
Cursor query(String table, String[] columns, String selection, String[] selectionArgs,
String groupBy, String having, String orderBy)
table是表名;columns用于指定去查詢哪幾列,如果不指定則默認查詢所有列;selection和selectionArgs用于去約束查詢某一行或某幾行的數據,不指定則默認是查詢所有行的數據;groupBy用于指定需要去group by的列,不指定則表示不對查詢結果進行group by操作;having用于對group by之后的數據進行進一步的過濾,不指定則表示不進行過濾;orderBy用于指定查詢結果的排序方式,不指定則表示使用默認的排序方式。
示例演示
1)SQLiteOpenHelper幫助創建和更新數據庫
public class DBOpenHelper extends SQLiteOpenHelper {
private Context mContext;
private String createBook;
private String createCategory;
public DBOpenHelper(Context context, String name,
SQLiteDatabase.CursorFactory factory, int version) {
super(context, name, factory, version);
mContext = context;
}
/**
* 創建數據庫
*/
@Override
public void onCreate(SQLiteDatabase db) {
// 創建book表
createBook = "create table book(" +
"id integer primary key autoincrement, " +
"author text, " +
"price real, " +
"pages integer, " +
"name text, " +
"category_id integer)";
db.execSQL(createBook);
// 創建category表
createCategory = "create table category(" +
"id integer primary key autoincrement, " +
"category_name text, " +
"category_code integer)";
db.execSQL(createCategory);
// 提示數據庫創建完畢
Toast.makeText(mContext, "數據庫創建完畢", Toast.LENGTH_SHORT).show();
}
/**
* 更新數據庫
*/
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
switch (oldVersion) {
case 1:
// 創建category表
db.execSQL(createCategory);
case 2:
// 向book表添加category_id列
db.execSQL("alter table book add column category_id integer");
break;
}
}
}
2)設置Activity的布局
activity_main.xml
<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/add_data"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="添加數據"/>
<Button
android:id="@+id/update_data"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="更新數據"/>
<Button
android:id="@+id/delete_data"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="刪除數據"/>
<Button
android:id="@+id/query_data"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="查詢數據"/>
</LinearLayout>
3)在Activity中進行數據庫的CRUD操作
MainActivity.java
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
private DBOpenHelper mDBOpenHelper;
private SQLiteDatabase mSqLiteDatabase;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 數據庫BookStore.db,版本2。
mDBOpenHelper = new DBOpenHelper(this, "BookStore.db", null, 2);
/**
* 插入數據
*/
findViewById(R.id.add_data).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// 以可寫入的方式獲取數據庫
mSqLiteDatabase = mDBOpenHelper.getWritableDatabase();
// 創建ContentValues并寫入數據
ContentValues values = new ContentValues();
values.put("name", "The Da Vinci Code");
values.put("author", "Dan Brown");
values.put("pages", 454);
values.put("price", 16.96);
// 插入第一條數據
mSqLiteDatabase.insert("book", null, values);
// 清空ContentValues
values.clear();
values.put("name", "The Lost Symbol");
values.put("author", "Dan Brown");
values.put("pages", 510);
values.put("price", 19.95);
// 插入第二條數據
mSqLiteDatabase.insert("book", null, values);
// 清空ContentValues
values.clear();
Toast.makeText(MainActivity.this, "已插入數據", Toast.LENGTH_SHORT).show();
}
});
/**
* 更新數據
*/
findViewById(R.id.update_data).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// 以可寫入的方式獲取數據庫
mSqLiteDatabase = mDBOpenHelper.getWritableDatabase();
// 創建ContentValues并寫入數據
ContentValues values = new ContentValues();
values.put("price", 10.99);
// 更新數據
mSqLiteDatabase.update("book", values,
"name = ?", new String[]{"The Da Vinci Code"});
Toast.makeText(MainActivity.this, "已更新數據", Toast.LENGTH_SHORT).show();
}
});
/**
* 刪除數據
*/
findViewById(R.id.delete_data).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// 以可寫入的方式獲取數據庫
mSqLiteDatabase = mDBOpenHelper.getWritableDatabase();
mSqLiteDatabase.delete("book", "pages > ?", new String[]{"500"});
Toast.makeText(MainActivity.this, "已刪除數據", Toast.LENGTH_SHORT).show();
}
});
/**
* 查詢數據
*/
findViewById(R.id.query_data).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// 以只讀的方式獲取數據庫
mSqLiteDatabase = mDBOpenHelper.getReadableDatabase();
// 查詢book表中所有數據
Cursor cursor = mSqLiteDatabase.query("book", null, null, null, null, null, null);
// 遍歷Cursor對象,取出數據。
while (cursor.moveToNext()) {
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.i(TAG, "name: " + name + ", author: " + author +
", pages: " + pages + ", price: " + price);
}
// 記得關閉資源
cursor.close();
Toast.makeText(MainActivity.this, "已查詢數據", Toast.LENGTH_SHORT).show();
}
});
}
}
使用事務
SQLiteDatabase db = dbHelper.getWritableDatabase();
// 開啟事務
db.beginTransaction();
try {
db.delete("Book", null, null);
ContentValues values = new ContentValues();
values.put("name", "Game of Thrones");
values.put("author", "George Martin");
values.put("pages", 720);
values.put("price", 20.85);
db.insert("Book", null, values);
// 操作成功
db.setTransactionSuccessful();
} catch (Exception e) {
e.printStackTrace();
} finally {
// 關閉事務
db.endTransaction();
}
參考
《第一行代碼--Android》
Android--數據持久化之SQLite