6.3 KiB
6.3 KiB
SQLite数据库
目录
SQLite基础
SQLite 简介
// SQLite:轻量级关系型数据库
// - 嵌入式数据库
// - 无需服务器
// - 支持 SQL 语法
// - 适合移动应用
创建数据库
public class DatabaseHelper extends SQLiteOpenHelper {
private static final String DATABASE_NAME = "my_database.db";
private static final int DATABASE_VERSION = 1;
public DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
// 创建表
db.execSQL("CREATE TABLE user (" +
"id INTEGER PRIMARY KEY AUTOINCREMENT," +
"name TEXT NOT NULL," +
"email TEXT," +
"age INTEGER" +
")");
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// 升级数据库
db.execSQL("DROP TABLE IF EXISTS user");
onCreate(db);
}
}
SQLite操作
插入数据
// 方式1:使用 execSQL
db.execSQL("INSERT INTO user (name, email, age) VALUES (?, ?, ?)",
new String[]{"John", "john@example.com", "25"});
// 方式2:使用 insert
ContentValues values = new ContentValues();
values.put("name", "John");
values.put("email", "john@example.com");
values.put("age", 25);
long id = db.insert("user", null, values);
查询数据
// 查询所有
Cursor cursor = db.query("user", null, null, null, null, null, null);
// 条件查询
Cursor cursor = db.query("user",
new String[]{"id", "name", "email"},
"age > ?",
new String[]{"18"},
null, null, "name ASC");
// 使用 SQL
Cursor cursor = db.rawQuery("SELECT * FROM user WHERE age > ?", new String[]{"18"});
// 遍历结果
while (cursor.moveToNext()) {
int id = cursor.getInt(cursor.getColumnIndex("id"));
String name = cursor.getString(cursor.getColumnIndex("name"));
String email = cursor.getString(cursor.getColumnIndex("email"));
}
cursor.close();
更新数据
// 方式1:使用 execSQL
db.execSQL("UPDATE user SET name = ? WHERE id = ?",
new String[]{"Jane", "1"});
// 方式2:使用 update
ContentValues values = new ContentValues();
values.put("name", "Jane");
int count = db.update("user", values, "id = ?", new String[]{"1"});
删除数据
// 方式1:使用 execSQL
db.execSQL("DELETE FROM user WHERE id = ?", new String[]{"1"});
// 方式2:使用 delete
int count = db.delete("user", "id = ?", new String[]{"1"});
SQLite性能优化
1. 使用索引
// 创建索引
db.execSQL("CREATE INDEX idx_name ON user(name)");
2. 使用事务
// 批量操作使用事务
db.beginTransaction();
try {
for (int i = 0; i < 1000; i++) {
db.insert("user", null, values);
}
db.setTransactionSuccessful();
} finally {
db.endTransaction();
}
3. 使用预编译语句
// 使用 SQLiteStatement
SQLiteStatement stmt = db.compileStatement(
"INSERT INTO user (name, email) VALUES (?, ?)");
stmt.bindString(1, "John");
stmt.bindString(2, "john@example.com");
stmt.executeInsert();
stmt.close();
4. 避免 N+1 查询
// ❌ 问题:N+1 查询
List<User> users = getUsers();
for (User user : users) {
List<Order> orders = getOrdersByUserId(user.getId()); // N 次查询
}
// ✅ 解决:使用 JOIN
SELECT u.*, o.* FROM user u LEFT JOIN order o ON u.id = o.user_id
SQLite事务
事务使用
// 开始事务
db.beginTransaction();
try {
// 执行多个操作
db.insert("user", null, values1);
db.insert("user", null, values2);
db.insert("user", null, values3);
// 标记事务成功
db.setTransactionSuccessful();
} finally {
// 结束事务(如果未标记成功,会回滚)
db.endTransaction();
}
事务优势
// 1. 原子性:要么全部成功,要么全部失败
// 2. 性能:批量操作性能更好
// 3. 一致性:保证数据一致性
SQLite索引
创建索引
// 单列索引
db.execSQL("CREATE INDEX idx_name ON user(name)");
// 复合索引
db.execSQL("CREATE INDEX idx_name_age ON user(name, age)");
// 唯一索引
db.execSQL("CREATE UNIQUE INDEX idx_email ON user(email)");
索引使用
// 索引会加速查询
// 但会增加写入开销和存储空间
// 适合创建索引的列:
// 1. 经常用于 WHERE 条件的列
// 2. 经常用于 JOIN 的列
// 3. 经常用于 ORDER BY 的列
SQLite最佳实践
1. 使用事务
// 批量操作使用事务
db.beginTransaction();
try {
// 批量操作
db.setTransactionSuccessful();
} finally {
db.endTransaction();
}
2. 及时关闭 Cursor
// ✅ 正确
Cursor cursor = db.query(...);
try {
// 使用 cursor
} finally {
cursor.close();
}
// ❌ 错误:忘记关闭
Cursor cursor = db.query(...);
// 使用 cursor
// 忘记关闭,可能导致内存泄漏
3. 使用预编译语句
// 重复执行的 SQL 使用预编译语句
SQLiteStatement stmt = db.compileStatement("INSERT INTO user (name) VALUES (?)");
4. 数据库升级
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// 根据版本号升级
if (oldVersion < 2) {
// 升级到版本2
}
if (oldVersion < 3) {
// 升级到版本3
}
}
面试常见问题
Q1: SQLite 的特点?
答案:
- 轻量级关系型数据库
- 嵌入式数据库,无需服务器
- 支持 SQL 语法
- 适合移动应用
Q2: 如何优化 SQLite 性能?
答案:
- 使用索引
- 使用事务
- 使用预编译语句
- 避免 N+1 查询
Q3: SQLite 事务的作用?
答案:
- 原子性:保证操作要么全部成功,要么全部失败
- 性能:批量操作性能更好
- 一致性:保证数据一致性
Q4: 什么时候创建索引?
答案:
- 经常用于 WHERE 条件的列
- 经常用于 JOIN 的列
- 经常用于 ORDER BY 的列
最后更新:2024年