安卓查询数据库代码怎么写
- 数据库
- 2025-08-18
- 3
安卓开发中,查询数据库是一项基础且核心的操作,以下是详细的实现步骤、代码示例及注意事项:
SQLite数据库的基本使用流程
- 创建/打开数据库:通过
SQLiteOpenHelper
子类管理数据库版本升级和创建逻辑,例如定义一个继承自它的辅助类,重写onCreate()
方法执行建表语句; - 获取可写或只读数据库实例:调用
getWritableDatabase()
或getReadableDatabase()
获得访问对象; - 执行SQL操作:使用
execSQL()
直接运行DDL语句,或通过rawQuery()
/query()
方法进行数据检索; - 处理结果集:利用
Cursor
对象遍历查询结果并提取字段值; - 关闭资源:及时释放Cursor和数据库连接以避免内存泄漏。
具体代码实现(含完整案例)
步骤1:定义数据库帮助类
public class MyDatabaseHelper extends SQLiteOpenHelper { private static final String DATABASE_NAME = "user_management.db"; // 数据库名称 private static final int VERSION = 1; // 版本号 // 构造函数,传入上下文环境 public MyDatabaseHelper(Context context) { super(context, DATABASE_NAME, null, VERSION); } @Override public void onCreate(SQLiteDatabase db) { String createTableSQL = "CREATE TABLE IF NOT EXISTS users(" + "id INTEGER PRIMARY KEY AUTOINCREMENT, " + "name TEXT NOT NULL, " + "age INTEGER, " + "email TEXT UNIQUE);"; db.execSQL(createTableSQL); // 执行建表语句 } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { // 简单策略:删除旧表后重建(实际项目建议迁移数据) db.execSQL("DROP TABLE IF EXISTS users"); onCreate(db); } }
关键点解析:
onCreate
仅在第一次安装时触发,而onUpgrade
处理版本迭代时的结构调整,此处采用暴力重建方式,生产环境应考虑数据迁移方案。
步骤2:插入测试数据(可选)
// 在Activity或其他地方调用 MyDatabaseHelper helper = new MyDatabaseHelper(this); SQLiteDatabase db = helper.getWritableDatabase(); ContentValues values = new ContentValues(); values.put("name", "张三"); values.put("age", 25); values.put("email", "zhangsan@example.com"); db.insert("users", null, values); // 第三个参数为null时自动填充_id列 db.close(); // 记得关闭连接!
替代方案:也可以使用
execSQL
插入多行记录,但ContentValues
更适合单条数据的键值对映射。
步骤3:实现查询功能
以下是三种主流查询方式的对比实现:
| 方法类型 | 适用场景 | 优点 | 缺点 |
|—————-|——————————|———————–|———————|
| rawQuery()
| 复杂条件拼接(如动态WHERE子句)| 支持参数化防注入 | SQL语法易出错 |
| query()
| 标准化简单查询 | 类型安全,API清晰 | 难以表达复杂逻辑 |
| SQLite语句预编译| 高频重复执行相同结构查询 | 提升性能,减少解析开销| 代码稍显冗长 |
原生SQL+rawQuery()
String selectSql = "SELECT FROM users WHERE age > ? AND name LIKE ?"; String[] selectionArgs = {"20", "%李%"}; // 占位符的实际参数值 Cursor cursor = db.rawQuery(selectSql, selectionArgs); while (cursor.moveToNext()) { int idIndex = cursor.getColumnIndex("id"); String name = cursor.getString(cursor.getColumnIndex("name")); int age = cursor.getInt(cursor.getColumnIndex("age")); Log.d("DB_RESULT", "找到用户:" + name + ", 年龄:" + age); } cursor.close(); // 确保资源释放!
安全警示:永远不要直接拼接外部输入到SQL字符串中!必须使用问号占位符配合
selectionArgs
数组来防止SQL注入攻击。
标准化API+query()
// 参数说明:表名、要获取的列数组、where条件、占位符参数、分组方式等 String[] columns = {"id", "name", "age"}; String selection = "age >= ?"; // WHERE age >= ? String[] args = {"18"}; // 对应一个问号的位置参数 String groupBy = null; // 不需要分组时置空 String having = null; // HAVING子句同理 String orderBy = "age DESC"; // 按年龄降序排列 String limit = "5"; // 最多返回5条记录 Cursor cursor = db.query( "users", // 目标表名 columns, // 需要返回的列集合 selection, // WHERE子句条件表达式 args, // 替换WHERE中的?的实际值数组 groupBy, // GROUP BY子句内容 having, // HAVING子句内容 orderBy, // 排序方式描述 limit // 分页限制数量 ); if (cursor != null) { while (cursor.moveToNext()) { int id = cursor.getInt(cursor.getColumnIndexOrThrow("id")); String userName = cursor.getString(cursor.getColumnIndexOrThrow("name")); // 其他字段类似处理... } cursor.close(); }
异常处理建议:当不确定某列是否存在时,优先用
getColumnIndexOrThrow()
会抛出明确错误而非静默失败。
预编译语句提升效率
// 准备预处理语句对象 SQLiteStatement stmt = db.compileStatement( "INSERT INTO users (name, age) VALUES (?, ?)"); // 绑定参数并执行多次插入 stmt.bindString(1, "王五"); stmt.bindLong(2, 30L); stmt.executeInsert(); stmt.clearBindings(); // 清除当前绑定以便下次使用 stmt.bindString(1, "赵六"); stmt.bindLong(2, 28L); stmt.executeInsert(); stmt.close(); // 最终关闭声明对象
性能优势:对于批量插入场景,预编译语句比原始SQL执行速度快约30%~50%。
最佳实践清单
- 事务批量操作:当需要进行多个相关修改时,启用事务保证原子性:
db.beginTransaction(); // 开启事务 try { // ...一系列数据库操作... db.setTransactionSuccessful(); //标记成功提交 } finally { db.endTransaction(); // 无论成败都要结束事务 }
- 游标生命周期管理:始终在
finally
块或try-with-resources中关闭Cursor,避免造成内存溢出; - 索引优化:对高频查询字段建立索引加速响应速度;
- 异步线程处理:将大数据量的读写放在后台线程执行,避免阻塞主线程导致ANR;
- 使用ORM框架简化开发:如Room库提供编译期校验的类型安全访问层,大幅降低手写SQL出错概率。
FAQs常见问题解答
Q1:为什么有时候查不到预期的数据?
A:可能原因包括:①未正确关闭之前的Cursor导致缓存不一致;②事务未提交即读取;③SQL条件表达式书写错误(特别是日期格式比较);④数据库文件被意外覆盖,建议开启日志输出完整的SQL语句进行调试。
Q2:如何查看手机上的实际数据库文件?
A:有两种方法:①通过Android Studio的Device File Explorer面板导航至/data/data/包名/databases路径导出文件;②使用第三方工具如Stetho库集成到应用内,或者连接真机后用adb pull命令拷贝到本地分析,注意调试版