Android使用SQLiteDatabase增刪改查(CRUD)的操作教程
1. 初始化數(shù)據(jù)庫
首先需要獲取數(shù)據(jù)庫實(shí)例:
// 創(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, // 當(dāng)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); } // 標(biāo)記事務(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. 最佳實(shí)踐
- 始終關(guān)閉Cursor和數(shù)據(jù)庫連接:避免內(nèi)存泄漏
- 使用事務(wù)處理批量操作:提高性能
- 避免在主線程執(zhí)行耗時操作:數(shù)據(jù)庫操作應(yīng)在子線程中進(jìn)行
- 使用參數(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 進(jìn)行增刪改查的詳細(xì)操作。隨著 Android 的發(fā)展,Google 推薦使用 Room 持久化庫來替代直接使用 SQLiteDatabase,它提供了更簡潔的 API 和編譯時 SQL 檢查。
動態(tài)SQLite幫助類實(shí)現(xiàn)
以下是一個改進(jì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ù)版本號進(jìn)行表結(jié)構(gòu)遷移 // 實(shí)際項(xiàng)目中需要更復(fù)雜的升級邏輯 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(); } } /** * 驗(yàn)證表是否存在 */ 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");
特點(diǎn)
- 動態(tài)表結(jié)構(gòu):不固定表和列,可以在運(yùn)行時創(chuàng)建任意結(jié)構(gòu)的表
- 完整的CRUD操作:提供插入、查詢、更新、刪除等完整操作
- 批量操作支持:支持批量插入數(shù)據(jù)
- 表結(jié)構(gòu)緩存:緩存表結(jié)構(gòu)信息,避免頻繁查詢系統(tǒng)表
- 類型安全:確保操作的表和列存在
- 事務(wù)支持:批量操作使用事務(wù)保證數(shù)據(jù)一致性
- 原始SQL支持:可以直接執(zhí)行原始SQL語句
這個實(shí)現(xiàn)可以根據(jù)需要進(jìn)一步擴(kuò)展,比如添加索引支持、更復(fù)雜的表結(jié)構(gòu)變更等功能。
以上就是Android使用SQLiteDatabase增刪改查(CRUD)的操作教程的詳細(xì)內(nèi)容,更多關(guān)于Android SQLiteDatabase增刪改查的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Android WiFi熱點(diǎn)開發(fā)的示例代碼
這篇文章主要介紹了Android WiFi熱點(diǎn)開發(fā)的示例代碼,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-09-09Android GuideView實(shí)現(xiàn)首次登陸引導(dǎo)
這篇文章主要為大家詳細(xì)介紹了Android GuideView實(shí)現(xiàn)首次登陸引導(dǎo),具有一定的參考價值,感興趣的小伙伴們可以參考一下2019-03-03代碼從windows下visual studio到andriod平臺遷移實(shí)現(xiàn)步驟
這篇文章主要介紹了代碼從windows下visual studio到andriod平臺遷移的修改記錄的相關(guān)資料,需要的朋友可以參考下2017-01-01Android實(shí)現(xiàn)USB掃碼槍獲取掃描內(nèi)容
這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)USB掃碼槍獲取掃描內(nèi)容,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2021-09-09ViewPager的setOnPageChangeListener方法詳解
這篇文章主要介紹了ViewPager的setOnPageChangeListener方法詳解,非常不錯,具有參考解決借鑒價值,需要的朋友可以參考下2016-12-12