文章目录
-
- [1. 初始化数据库](#1. 初始化数据库)
- [2. 插入数据 (Create)](#2. 插入数据 (Create))
-
- [方法一:使用 ContentValues + insert()](#方法一:使用 ContentValues + insert())
- 方法二:直接执行SQL
- [3. 查询数据 (Read)](#3. 查询数据 (Read))
-
- [方法一:使用 query() 方法](#方法一:使用 query() 方法)
- [方法二:使用 rawQuery() 执行原始SQL](#方法二:使用 rawQuery() 执行原始SQL)
- [4. 更新数据 (Update)](#4. 更新数据 (Update))
-
- [方法一:使用 ContentValues + update()](#方法一:使用 ContentValues + update())
- 方法二:直接执行SQL
- [5. 删除数据 (Delete)](#5. 删除数据 (Delete))
-
- [方法一:使用 delete() 方法](#方法一:使用 delete() 方法)
- 方法二:直接执行SQL
- [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. 最佳实践
- 始终关闭Cursor和数据库连接:避免内存泄漏
- 使用事务处理批量操作:提高性能
- 避免在主线程执行耗时操作:数据库操作应在子线程中进行
- 使用参数化查询:防止SQL注入
- 考虑使用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");
特点
- 动态表结构:不固定表和列,可以在运行时创建任意结构的表
- 完整的CRUD操作:提供插入、查询、更新、删除等完整操作
- 批量操作支持:支持批量插入数据
- 表结构缓存:缓存表结构信息,避免频繁查询系统表
- 类型安全:确保操作的表和列存在
- 事务支持:批量操作使用事务保证数据一致性
- 原始SQL支持:可以直接执行原始SQL语句
这个实现可以根据需要进一步扩展,比如添加索引支持、更复杂的表结构变更等功能。