# SQLite数据库

## 目录
- [SQLite基础](#sqlite基础)
- [SQLite操作](#sqlite操作)
- [SQLite性能优化](#sqlite性能优化)
- [SQLite事务](#sqlite事务)
- [SQLite索引](#sqlite索引)
- [SQLite最佳实践](#sqlite最佳实践)
- [面试常见问题](#面试常见问题)

---

## SQLite基础

### SQLite 简介

```java
// SQLite：轻量级关系型数据库
// - 嵌入式数据库
// - 无需服务器
// - 支持 SQL 语法
// - 适合移动应用
```

### 创建数据库

```java
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操作

### 插入数据

```java
// 方式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);
```

### 查询数据

```java
// 查询所有
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();
```

### 更新数据

```java
// 方式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"});
```

### 删除数据

```java
// 方式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. 使用索引

```java
// 创建索引
db.execSQL("CREATE INDEX idx_name ON user(name)");
```

### 2. 使用事务

```java
// 批量操作使用事务
db.beginTransaction();
try {
    for (int i = 0; i < 1000; i++) {
        db.insert("user", null, values);
    }
    db.setTransactionSuccessful();
} finally {
    db.endTransaction();
}
```

### 3. 使用预编译语句

```java
// 使用 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 查询

```java
// ❌ 问题：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事务

### 事务使用

```java
// 开始事务
db.beginTransaction();
try {
    // 执行多个操作
    db.insert("user", null, values1);
    db.insert("user", null, values2);
    db.insert("user", null, values3);
    
    // 标记事务成功
    db.setTransactionSuccessful();
} finally {
    // 结束事务（如果未标记成功，会回滚）
    db.endTransaction();
}
```

### 事务优势

```java
// 1. 原子性：要么全部成功，要么全部失败
// 2. 性能：批量操作性能更好
// 3. 一致性：保证数据一致性
```

---

## SQLite索引

### 创建索引

```java
// 单列索引
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)");
```

### 索引使用

```java
// 索引会加速查询
// 但会增加写入开销和存储空间

// 适合创建索引的列：
// 1. 经常用于 WHERE 条件的列
// 2. 经常用于 JOIN 的列
// 3. 经常用于 ORDER BY 的列
```

---

## SQLite最佳实践

### 1. 使用事务

```java
// 批量操作使用事务
db.beginTransaction();
try {
    // 批量操作
    db.setTransactionSuccessful();
} finally {
    db.endTransaction();
}
```

### 2. 及时关闭 Cursor

```java
// ✅ 正确
Cursor cursor = db.query(...);
try {
    // 使用 cursor
} finally {
    cursor.close();
}

// ❌ 错误：忘记关闭
Cursor cursor = db.query(...);
// 使用 cursor
// 忘记关闭，可能导致内存泄漏
```

### 3. 使用预编译语句

```java
// 重复执行的 SQL 使用预编译语句
SQLiteStatement stmt = db.compileStatement("INSERT INTO user (name) VALUES (?)");
```

### 4. 数据库升级

```java
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    // 根据版本号升级
    if (oldVersion < 2) {
        // 升级到版本2
    }
    if (oldVersion < 3) {
        // 升级到版本3
    }
}
```

---

## 面试常见问题

### Q1: SQLite 的特点？

**答案：**
- 轻量级关系型数据库
- 嵌入式数据库，无需服务器
- 支持 SQL 语法
- 适合移动应用

### Q2: 如何优化 SQLite 性能？

**答案：**
1. 使用索引
2. 使用事务
3. 使用预编译语句
4. 避免 N+1 查询

### Q3: SQLite 事务的作用？

**答案：**
1. 原子性：保证操作要么全部成功，要么全部失败
2. 性能：批量操作性能更好
3. 一致性：保证数据一致性

### Q4: 什么时候创建索引？

**答案：**
- 经常用于 WHERE 条件的列
- 经常用于 JOIN 的列
- 经常用于 ORDER BY 的列

---

*最后更新：2024年*
