Android使用SQLiteDatabase增刪改查(CRUD)的操作教程
1. 初始化數(shù)據(jù)庫
首先需要獲取數(shù)據(jù)庫實例:
// 創(chuàng)建或打開數(shù)據(jù)庫 DatabaseHelper dbHelper = new DatabaseHelper(context); SQLiteDatabase db = dbHelper.getWritableDatabase(); // 如果只需要讀取數(shù)據(jù),可以使用 // SQLiteDatabase db = dbHelper.getReadableDatabase();
2. 插入數(shù)據(jù) (Create)
方法一:使用 ContentValues + insert()
ContentValues values = new ContentValues();
values.put("name", "張三");
values.put("age", 25);
values.put("email", "zhangsan@example.com");
// 插入數(shù)據(jù),返回新行的ID,如果插入失敗返回-1
long newRowId = db.insert(
"users", // 表名
null, // 當values為空時,指定可以為null的列名
values // 要插入的數(shù)據(jù)
);
if(newRowId == -1) {
// 插入失敗處理
} else {
// 插入成功,newRowId是新記錄的主鍵值
}
方法二:直接執(zhí)行SQL
String sql = "INSERT INTO users (name, age, email) VALUES ('張三', 25, 'zhangsan@example.com')";
db.execSQL(sql);
3. 查詢數(shù)據(jù) (Read)
方法一:使用 query() 方法
// 查詢所有列
Cursor cursor = db.query(
"users", // 表名
null, // 要查詢的列名數(shù)組,null表示所有列
null, // WHERE子句,null表示無
null, // WHERE子句的參數(shù)
null, // GROUP BY子句
null, // HAVING子句
"age DESC" // ORDER BY子句
);
// 帶條件的查詢
String[] columns = {"name", "age"};
String selection = "age > ?";
String[] selectionArgs = {"20"};
String orderBy = "name ASC";
Cursor cursor = db.query(
"users",
columns,
selection,
selectionArgs,
null,
null,
orderBy
);
// 遍歷Cursor
while (cursor.moveToNext()) {
String name = cursor.getString(cursor.getColumnIndexOrThrow("name"));
int age = cursor.getInt(cursor.getColumnIndexOrThrow("age"));
// 處理數(shù)據(jù)...
}
// 記得關(guān)閉Cursor
cursor.close();
方法二:使用 rawQuery() 執(zhí)行原始SQL
String sql = "SELECT * FROM users WHERE age > ?";
Cursor cursor = db.rawQuery(sql, new String[]{"20"});
// 處理Cursor...
cursor.close();
4. 更新數(shù)據(jù) (Update)
方法一:使用 ContentValues + update()
ContentValues values = new ContentValues();
values.put("age", 26);
values.put("email", "new_email@example.com");
// 更新條件
String whereClause = "id = ?";
String[] whereArgs = {"1"};
// 更新數(shù)據(jù),返回受影響的行數(shù)
int count = db.update(
"users", // 表名
values, // 新值
whereClause, // WHERE子句
whereArgs // WHERE子句的參數(shù)
);
方法二:直接執(zhí)行SQL
String sql = "UPDATE users SET age = 26, email = 'new_email@example.com' WHERE id = 1"; db.execSQL(sql);
5. 刪除數(shù)據(jù) (Delete)
方法一:使用 delete() 方法
// 刪除條件
String whereClause = "id = ?";
String[] whereArgs = {"1"};
// 刪除數(shù)據(jù),返回被刪除的行數(shù)
int count = db.delete(
"users", // 表名
whereClause, // WHERE子句
whereArgs // WHERE子句的參數(shù)
);
方法二:直接執(zhí)行SQL
String sql = "DELETE FROM users WHERE id = 1"; db.execSQL(sql);
6. 事務(wù)處理
對于批量操作,使用事務(wù)可以提高性能并保證數(shù)據(jù)一致性:
db.beginTransaction();
try {
// 執(zhí)行多個數(shù)據(jù)庫操作
for (int i = 0; i < 100; i++) {
ContentValues values = new ContentValues();
values.put("name", "User " + i);
values.put("age", i % 50);
db.insert("users", null, values);
}
// 標記事務(wù)為成功
db.setTransactionSuccessful();
} catch (Exception e) {
// 處理異常
} finally {
// 結(jié)束事務(wù)
db.endTransaction();
}
7. 關(guān)閉數(shù)據(jù)庫
在不再需要數(shù)據(jù)庫連接時,應(yīng)該關(guān)閉它:
db.close(); dbHelper.close();
8. 最佳實踐
- 始終關(guān)閉Cursor和數(shù)據(jù)庫連接:避免內(nèi)存泄漏
- 使用事務(wù)處理批量操作:提高性能
- 避免在主線程執(zhí)行耗時操作:數(shù)據(jù)庫操作應(yīng)在子線程中進行
- 使用參數(shù)化查詢:防止SQL注入
- 考慮使用Room:Android官方推薦的SQLite ORM庫
完整示例
public class UserDao {
private DatabaseHelper dbHelper;
public UserDao(Context context) {
dbHelper = new DatabaseHelper(context);
}
// 添加用戶
public long addUser(User user) {
SQLiteDatabase db = dbHelper.getWritableDatabase();
ContentValues values = new ContentValues();
values.put("name", user.getName());
values.put("age", user.getAge());
values.put("email", user.getEmail());
long id = db.insert("users", null, values);
db.close();
return id;
}
// 獲取所有用戶
public List<User> getAllUsers() {
List<User> userList = new ArrayList<>();
SQLiteDatabase db = dbHelper.getReadableDatabase();
Cursor cursor = db.query("users", null, null, null, null, null, "name ASC");
while (cursor.moveToNext()) {
User user = new User();
user.setId(cursor.getInt(cursor.getColumnIndexOrThrow("id")));
user.setName(cursor.getString(cursor.getColumnIndexOrThrow("name")));
user.setAge(cursor.getInt(cursor.getColumnIndexOrThrow("age")));
user.setEmail(cursor.getString(cursor.getColumnIndexOrThrow("email")));
userList.add(user);
}
cursor.close();
db.close();
return userList;
}
// 更新用戶
public int updateUser(User user) {
SQLiteDatabase db = dbHelper.getWritableDatabase();
ContentValues values = new ContentValues();
values.put("name", user.getName());
values.put("age", user.getAge());
values.put("email", user.getEmail());
int count = db.update(
"users",
values,
"id = ?",
new String[]{String.valueOf(user.getId())}
);
db.close();
return count;
}
// 刪除用戶
public int deleteUser(int userId) {
SQLiteDatabase db = dbHelper.getWritableDatabase();
int count = db.delete(
"users",
"id = ?",
new String[]{String.valueOf(userId)}
);
db.close();
return count;
}
// 關(guān)閉數(shù)據(jù)庫幫助類
public void close() {
dbHelper.close();
}
}
以上就是在 Android 中使用 SQLiteDatabase 進行增刪改查的詳細操作。隨著 Android 的發(fā)展,Google 推薦使用 Room 持久化庫來替代直接使用 SQLiteDatabase,它提供了更簡潔的 API 和編譯時 SQL 檢查。
動態(tài)SQLite幫助類實現(xiàn)
以下是一個改進版的SQLite幫助類,不固定表和列結(jié)構(gòu),支持動態(tài)創(chuàng)建表和執(zhí)行CRUD操作:
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class DynamicDBHelper extends SQLiteOpenHelper {
private static final String TAG = "DynamicDBHelper";
private static final String DATABASE_NAME = "dynamic_db";
private static final int DATABASE_VERSION = 1;
private static DynamicDBHelper instance;
private SQLiteDatabase db;
// 表結(jié)構(gòu)緩存: key=表名, value=列定義map(列名->類型)
private Map<String, Map<String, String>> tableSchemas = new HashMap<>();
// 單例模式
public static synchronized DynamicDBHelper getInstance(Context context) {
if (instance == null) {
instance = new DynamicDBHelper(context.getApplicationContext());
}
return instance;
}
private DynamicDBHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
db = getWritableDatabase();
}
@Override
public void onCreate(SQLiteDatabase db) {
// 不在這里創(chuàng)建固定表,通過外部調(diào)用createTable方法動態(tài)創(chuàng)建
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// 可以根據(jù)版本號進行表結(jié)構(gòu)遷移
// 實際項目中需要更復雜的升級邏輯
for (String tableName : tableSchemas.keySet()) {
db.execSQL("DROP TABLE IF EXISTS " + tableName);
}
tableSchemas.clear();
}
/**
* 動態(tài)創(chuàng)建表
* @param tableName 表名
* @param columns 列定義map(列名 -> 數(shù)據(jù)類型,如 "TEXT", "INTEGER"等)
* @param primaryKey 主鍵列名(可選)
*/
public void createTable(String tableName, Map<String, String> columns, String primaryKey) {
if (tableExists(tableName)) {
Log.w(TAG, "Table " + tableName + " already exists");
return;
}
StringBuilder sql = new StringBuilder("CREATE TABLE " + tableName + " (");
// 添加列定義
for (Map.Entry<String, String> entry : columns.entrySet()) {
String columnName = entry.getKey();
String columnType = entry.getValue();
sql.append(columnName).append(" ").append(columnType).append(", ");
}
// 添加主鍵
if (primaryKey != null && !primaryKey.isEmpty()) {
sql.append("PRIMARY KEY (").append(primaryKey).append(")");
} else {
// 移除最后的逗號和空格
sql.delete(sql.length() - 2, sql.length());
}
sql.append(")");
db.execSQL(sql.toString());
tableSchemas.put(tableName, new HashMap<>(columns));
Log.d(TAG, "Table created: " + tableName);
}
/**
* 檢查表是否存在
*/
public boolean tableExists(String tableName) {
Cursor cursor = db.rawQuery(
"SELECT name FROM sqlite_master WHERE type='table' AND name=?",
new String[]{tableName});
boolean exists = cursor.getCount() > 0;
cursor.close();
return exists;
}
/**
* 插入數(shù)據(jù)
* @param tableName 表名
* @param values 數(shù)據(jù)鍵值對
* @return 新插入行的ID
*/
public long insert(String tableName, ContentValues values) {
validateTable(tableName);
return db.insert(tableName, null, values);
}
/**
* 批量插入數(shù)據(jù)
* @param tableName 表名
* @param valuesList 數(shù)據(jù)鍵值對列表
* @return 成功插入的數(shù)量
*/
public int bulkInsert(String tableName, List<ContentValues> valuesList) {
validateTable(tableName);
int count = 0;
try {
db.beginTransaction();
for (ContentValues values : valuesList) {
if (db.insert(tableName, null, values) != -1) {
count++;
}
}
db.setTransactionSuccessful();
} finally {
db.endTransaction();
}
return count;
}
/**
* 查詢數(shù)據(jù)
* @param tableName 表名
* @param columns 要查詢的列
* @param selection WHERE條件
* @param selectionArgs WHERE條件參數(shù)
* @param orderBy 排序
* @return 查詢結(jié)果的Cursor
*/
public Cursor query(String tableName, String[] columns, String selection,
String[] selectionArgs, String orderBy) {
validateTable(tableName);
return db.query(tableName, columns, selection, selectionArgs,
null, null, orderBy);
}
/**
* 查詢所有數(shù)據(jù)
* @param tableName 表名
* @return 包含所有行的Cursor
*/
public Cursor queryAll(String tableName) {
return query(tableName, null, null, null, null);
}
/**
* 更新數(shù)據(jù)
* @param tableName 表名
* @param values 要更新的值
* @param selection WHERE條件
* @param selectionArgs WHERE條件參數(shù)
* @return 受影響的行數(shù)
*/
public int update(String tableName, ContentValues values, String selection,
String[] selectionArgs) {
validateTable(tableName);
return db.update(tableName, values, selection, selectionArgs);
}
/**
* 刪除數(shù)據(jù)
* @param tableName 表名
* @param selection WHERE條件
* @param selectionArgs WHERE條件參數(shù)
* @return 受影響的行數(shù)
*/
public int delete(String tableName, String selection, String[] selectionArgs) {
validateTable(tableName);
return db.delete(tableName, selection, selectionArgs);
}
/**
* 刪除表中所有數(shù)據(jù)
* @param tableName 表名
* @return 受影響的行數(shù)
*/
public int deleteAll(String tableName) {
return delete(tableName, null, null);
}
/**
* 刪除表
* @param tableName 表名
*/
public void dropTable(String tableName) {
if (tableExists(tableName)) {
db.execSQL("DROP TABLE " + tableName);
tableSchemas.remove(tableName);
Log.d(TAG, "Table dropped: " + tableName);
}
}
/**
* 添加列
* @param tableName 表名
* @param columnName 列名
* @param columnType 列類型
*/
public void addColumn(String tableName, String columnName, String columnType) {
validateTable(tableName);
if (!tableSchemas.get(tableName).containsKey(columnName)) {
db.execSQL("ALTER TABLE " + tableName + " ADD COLUMN " + columnName + " " + columnType);
tableSchemas.get(tableName).put(columnName, columnType);
Log.d(TAG, "Column " + columnName + " added to table " + tableName);
} else {
Log.w(TAG, "Column " + columnName + " already exists in table " + tableName);
}
}
/**
* 執(zhí)行原始SQL查詢
* @param sql SQL語句
* @param selectionArgs 參數(shù)
* @return 結(jié)果Cursor
*/
public Cursor rawQuery(String sql, String[] selectionArgs) {
return db.rawQuery(sql, selectionArgs);
}
/**
* 執(zhí)行原始SQL語句
* @param sql SQL語句
*/
public void execSQL(String sql) {
db.execSQL(sql);
}
/**
* 關(guān)閉數(shù)據(jù)庫連接
*/
public void closeDB() {
if (db != null && db.isOpen()) {
db.close();
}
}
/**
* 驗證表是否存在
*/
private void validateTable(String tableName) {
if (!tableSchemas.containsKey(tableName)) {
throw new IllegalArgumentException("Table " + tableName + " does not exist");
}
}
/**
* 獲取表的列信息
* @param tableName 表名
* @return 列名到類型的映射
*/
public Map<String, String> getTableColumns(String tableName) {
validateTable(tableName);
return new HashMap<>(tableSchemas.get(tableName));
}
}
使用示例
// 初始化
DynamicDBHelper dbHelper = DynamicDBHelper.getInstance(context);
// 創(chuàng)建表
Map<String, String> columns = new HashMap<>();
columns.put("id", "INTEGER");
columns.put("name", "TEXT");
columns.put("age", "INTEGER");
columns.put("email", "TEXT");
dbHelper.createTable("users", columns, "id");
// 插入數(shù)據(jù)
ContentValues values = new ContentValues();
values.put("name", "張三");
values.put("age", 25);
values.put("email", "zhangsan@example.com");
long id = dbHelper.insert("users", values);
// 查詢數(shù)據(jù)
Cursor cursor = dbHelper.query("users", null, "age > ?", new String[]{"20"}, "name ASC");
while (cursor.moveToNext()) {
String name = cursor.getString(cursor.getColumnIndex("name"));
int age = cursor.getInt(cursor.getColumnIndex("age"));
// 處理數(shù)據(jù)...
}
cursor.close();
// 更新數(shù)據(jù)
ContentValues updateValues = new ContentValues();
updateValues.put("age", 26);
dbHelper.update("users", updateValues, "name = ?", new String[]{"張三"});
// 刪除數(shù)據(jù)
dbHelper.delete("users", "age < ?", new String[]{"18"});
// 添加新列
dbHelper.addColumn("users", "address", "TEXT");
// 刪除表
dbHelper.dropTable("users");
特點
- 動態(tài)表結(jié)構(gòu):不固定表和列,可以在運行時創(chuàng)建任意結(jié)構(gòu)的表
- 完整的CRUD操作:提供插入、查詢、更新、刪除等完整操作
- 批量操作支持:支持批量插入數(shù)據(jù)
- 表結(jié)構(gòu)緩存:緩存表結(jié)構(gòu)信息,避免頻繁查詢系統(tǒng)表
- 類型安全:確保操作的表和列存在
- 事務(wù)支持:批量操作使用事務(wù)保證數(shù)據(jù)一致性
- 原始SQL支持:可以直接執(zhí)行原始SQL語句
這個實現(xiàn)可以根據(jù)需要進一步擴展,比如添加索引支持、更復雜的表結(jié)構(gòu)變更等功能。
以上就是Android使用SQLiteDatabase增刪改查(CRUD)的操作教程的詳細內(nèi)容,更多關(guān)于Android SQLiteDatabase增刪改查的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Android GuideView實現(xiàn)首次登陸引導
這篇文章主要為大家詳細介紹了Android GuideView實現(xiàn)首次登陸引導,具有一定的參考價值,感興趣的小伙伴們可以參考一下2019-03-03
代碼從windows下visual studio到andriod平臺遷移實現(xiàn)步驟
這篇文章主要介紹了代碼從windows下visual studio到andriod平臺遷移的修改記錄的相關(guān)資料,需要的朋友可以參考下2017-01-01
Android實現(xiàn)USB掃碼槍獲取掃描內(nèi)容
這篇文章主要為大家詳細介紹了Android實現(xiàn)USB掃碼槍獲取掃描內(nèi)容,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2021-09-09
ViewPager的setOnPageChangeListener方法詳解
這篇文章主要介紹了ViewPager的setOnPageChangeListener方法詳解,非常不錯,具有參考解決借鑒價值,需要的朋友可以參考下2016-12-12

