SQLiteDatabase 增删改查(CRUD)详细操作

文章目录

    • [1. 初始化数据库](#1. 初始化数据库)
    • [2. 插入数据 (Create)](#2. 插入数据 (Create))
    • [3. 查询数据 (Read)](#3. 查询数据 (Read))
      • [方法一:使用 query() 方法](#方法一:使用 query() 方法)
      • [方法二:使用 rawQuery() 执行原始SQL](#方法二:使用 rawQuery() 执行原始SQL)
    • [4. 更新数据 (Update)](#4. 更新数据 (Update))
    • [5. 删除数据 (Delete)](#5. 删除数据 (Delete))
    • [6. 事务处理](#6. 事务处理)
    • [7. 关闭数据库](#7. 关闭数据库)
    • [8. 最佳实践](#8. 最佳实践)
    • 完整示例
  • 动态SQLite帮助类实现

在 Android 中使用 SQLiteDatabase 进行增删改查操作是开发中的核心技能之一。下面我将详细说明如何使用 SQLiteDatabase 进行 CRUD 操作。

1. 初始化数据库

首先需要获取数据库实例:

java 复制代码
// 创建或打开数据库
DatabaseHelper dbHelper = new DatabaseHelper(context);
SQLiteDatabase db = dbHelper.getWritableDatabase();

// 如果只需要读取数据,可以使用
// SQLiteDatabase db = dbHelper.getReadableDatabase();

2. 插入数据 (Create)

方法一:使用 ContentValues + insert()

java 复制代码
ContentValues values = new ContentValues();
values.put("name", "张三");
values.put("age", 25);
values.put("email", "[email protected]");

// 插入数据,返回新行的ID,如果插入失败返回-1
long newRowId = db.insert(
    "users",       // 表名
    null,          // 当values为空时,指定可以为null的列名
    values         // 要插入的数据
);

if(newRowId == -1) {
    // 插入失败处理
} else {
    // 插入成功,newRowId是新记录的主键值
}

方法二:直接执行SQL

java 复制代码
String sql = "INSERT INTO users (name, age, email) VALUES ('张三', 25, '[email protected]')";
db.execSQL(sql);

3. 查询数据 (Read)

方法一:使用 query() 方法

java 复制代码
// 查询所有列
Cursor cursor = db.query(
    "users",      // 表名
    null,         // 要查询的列名数组,null表示所有列
    null,         // WHERE子句,null表示无
    null,         // WHERE子句的参数
    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"));
    // 处理数据...
}

// 记得关闭Cursor
cursor.close();

方法二:使用 rawQuery() 执行原始SQL

java 复制代码
String sql = "SELECT * FROM users WHERE age > ?";
Cursor cursor = db.rawQuery(sql, new String[]{"20"});

// 处理Cursor...
cursor.close();

4. 更新数据 (Update)

方法一:使用 ContentValues + update()

java 复制代码
ContentValues values = new ContentValues();
values.put("age", 26);
values.put("email", "[email protected]");

// 更新条件
String whereClause = "id = ?";
String[] whereArgs = {"1"};

// 更新数据,返回受影响的行数
int count = db.update(
    "users",      // 表名
    values,       // 新值
    whereClause,  // WHERE子句
    whereArgs     // WHERE子句的参数
);

方法二:直接执行SQL

java 复制代码
String sql = "UPDATE users SET age = 26, email = '[email protected]' WHERE id = 1";
db.execSQL(sql);

5. 删除数据 (Delete)

方法一:使用 delete() 方法

java 复制代码
// 删除条件
String whereClause = "id = ?";
String[] whereArgs = {"1"};

// 删除数据,返回被删除的行数
int count = db.delete(
    "users",      // 表名
    whereClause,  // WHERE子句
    whereArgs     // WHERE子句的参数
);

方法二:直接执行SQL

java 复制代码
String sql = "DELETE FROM users WHERE id = 1";
db.execSQL(sql);

6. 事务处理

对于批量操作,使用事务可以提高性能并保证数据一致性:

java 复制代码
db.beginTransaction();
try {
    // 执行多个数据库操作
    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);
    }
    
    // 标记事务为成功
    db.setTransactionSuccessful();
} catch (Exception e) {
    // 处理异常
} finally {
    // 结束事务
    db.endTransaction();
}

7. 关闭数据库

在不再需要数据库连接时,应该关闭它:

java 复制代码
db.close();
dbHelper.close();

8. 最佳实践

  1. 始终关闭Cursor和数据库连接:避免内存泄漏
  2. 使用事务处理批量操作:提高性能
  3. 避免在主线程执行耗时操作:数据库操作应在子线程中进行
  4. 使用参数化查询:防止SQL注入
  5. 考虑使用Room:Android官方推荐的SQLite ORM库

完整示例

java 复制代码
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;
    }
    
    // 关闭数据库帮助类
    public void close() {
        dbHelper.close();
    }
}

以上就是在 Android 中使用 SQLiteDatabase 进行增删改查的详细操作。随着 Android 的发展,Google 推荐使用 Room 持久化库来替代直接使用 SQLiteDatabase,它提供了更简洁的 API 和编译时 SQL 检查。


动态SQLite帮助类实现

以下是一个改进版的SQLite帮助类,不固定表和列结构,支持动态创建表和执行CRUD操作:

java 复制代码
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;

    // 表结构缓存: 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) {
        // 不在这里创建固定表,通过外部调用createTable方法动态创建
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        // 可以根据版本号进行表结构迁移
        // 实际项目中需要更复杂的升级逻辑
        for (String tableName : tableSchemas.keySet()) {
            db.execSQL("DROP TABLE IF EXISTS " + tableName);
        }
        tableSchemas.clear();
    }

    /**
     * 动态创建表
     * @param tableName 表名
     * @param columns 列定义map(列名 -> 数据类型,如 "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;
    }

    /**
     * 插入数据
     * @param tableName 表名
     * @param values 数据键值对
     * @return 新插入行的ID
     */
    public long insert(String tableName, ContentValues values) {
        validateTable(tableName);
        return db.insert(tableName, null, values);
    }

    /**
     * 批量插入数据
     * @param tableName 表名
     * @param valuesList 数据键值对列表
     * @return 成功插入的数量
     */
    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;
    }

    /**
     * 查询数据
     * @param tableName 表名
     * @param columns 要查询的列
     * @param selection WHERE条件
     * @param selectionArgs WHERE条件参数
     * @param orderBy 排序
     * @return 查询结果的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);
    }

    /**
     * 查询所有数据
     * @param tableName 表名
     * @return 包含所有行的Cursor
     */
    public Cursor queryAll(String tableName) {
        return query(tableName, null, null, null, null);
    }

    /**
     * 更新数据
     * @param tableName 表名
     * @param values 要更新的值
     * @param selection WHERE条件
     * @param selectionArgs WHERE条件参数
     * @return 受影响的行数
     */
    public int update(String tableName, ContentValues values, String selection,
                     String[] selectionArgs) {
        validateTable(tableName);
        return db.update(tableName, values, selection, selectionArgs);
    }

    /**
     * 删除数据
     * @param tableName 表名
     * @param selection WHERE条件
     * @param selectionArgs WHERE条件参数
     * @return 受影响的行数
     */
    public int delete(String tableName, String selection, String[] selectionArgs) {
        validateTable(tableName);
        return db.delete(tableName, selection, selectionArgs);
    }

    /**
     * 删除表中所有数据
     * @param tableName 表名
     * @return 受影响的行数
     */
    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);
        }
    }

    /**
     * 执行原始SQL查询
     * @param sql SQL语句
     * @param selectionArgs 参数
     * @return 结果Cursor
     */
    public Cursor rawQuery(String sql, String[] selectionArgs) {
        return db.rawQuery(sql, selectionArgs);
    }

    /**
     * 执行原始SQL语句
     * @param sql SQL语句
     */
    public void execSQL(String sql) {
        db.execSQL(sql);
    }

    /**
     * 关闭数据库连接
     */
    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));
    }
}

使用示例

java 复制代码
// 初始化
DynamicDBHelper dbHelper = DynamicDBHelper.getInstance(context);

// 创建表
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");

// 插入数据
ContentValues values = new ContentValues();
values.put("name", "张三");
values.put("age", 25);
values.put("email", "[email protected]");
long id = dbHelper.insert("users", values);

// 查询数据
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"));
    // 处理数据...
}
cursor.close();

// 更新数据
ContentValues updateValues = new ContentValues();
updateValues.put("age", 26);
dbHelper.update("users", updateValues, "name = ?", new String[]{"张三"});

// 删除数据
dbHelper.delete("users", "age < ?", new String[]{"18"});

// 添加新列
dbHelper.addColumn("users", "address", "TEXT");

// 删除表
dbHelper.dropTable("users");

特点

  1. 动态表结构:不固定表和列,可以在运行时创建任意结构的表
  2. 完整的CRUD操作:提供插入、查询、更新、删除等完整操作
  3. 批量操作支持:支持批量插入数据
  4. 表结构缓存:缓存表结构信息,避免频繁查询系统表
  5. 类型安全:确保操作的表和列存在
  6. 事务支持:批量操作使用事务保证数据一致性
  7. 原始SQL支持:可以直接执行原始SQL语句

这个实现可以根据需要进一步扩展,比如添加索引支持、更复杂的表结构变更等功能。

相关推荐
时光书签21 分钟前
VSCode中安装GitGraph
ide·vscode·编辑器
xxy!22 分钟前
Spring 框架中用到的设计模式
java·spring·设计模式
东阳马生架构25 分钟前
Sentinel源码—7.参数限流和注解的实现二
java·sentinel
Klong.k28 分钟前
什么是 Stream
java·stream
曾经的三心草29 分钟前
博客系统-邮件发送-nginx-服务部署
java·数据库·nginx·邮件发送·服务部署
Java中文社群35 分钟前
聊聊SpringAI流式输出的底层实现?
java·人工智能·后端
Leaf吧1 小时前
java 设计模式 原型模式
java·设计模式·原型模式
super凹凸曼1 小时前
分享一个把你的API快速升级为MCP规范的方案,可在线体验
java·后端·开源
dora1 小时前
Flutter的屏幕适配
android·flutter
howeres1 小时前
Spring Boot 应用优雅关闭
java·spring boot