Qt 中使用 SQLite 数据库的完整指南
SQLite 是一款轻量级、嵌入式的关系型数据库,无需独立的服务器进程,数据以文件形式存储,非常适合桌面和移动端应用的本地数据管理。Qt 通过 Qt SQL 模块提供了对 SQLite 的原生支持,开发者可以轻松实现数据库的增删改查、事务处理等操作。本文将详细介绍如何在 Qt 中集成并使用 SQLite 数据库。
1. 环境配置与准备工作
1.1 启用 Qt SQL 模块
在 Qt 项目文件(.pro
)中添加 SQL 模块依赖:
QT += sql
1.2 包含头文件
在代码中引入必要的类:
#include <QSqlDatabase>
#include <QSqlQuery>
#include <QSqlError>
#include <QSqlTableModel>
2. 连接 SQLite 数据库
2.1 创建并打开数据库
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
db.setDatabaseName("my_database.db"); // 数据库文件名(或完整路径)
if (!db.open()) {
qDebug() << "Error: Failed to open database:" << db.lastError().text();
return;
}
-
说明:
-
QSQLITE
是 Qt 内置的 SQLite 驱动名称。 -
如果文件不存在,SQLite 会自动创建新数据库。
-
2.2 关闭数据库
db.close(); // 显式关闭连接(通常不需要,程序退出时自动关闭)
3. 执行 SQL 操作
3.1 创建表
QSqlQuery query;
query.exec("CREATE TABLE IF NOT EXISTS users ("
"id INTEGER PRIMARY KEY AUTOINCREMENT,"
"name TEXT NOT NULL,"
"age INTEGER,"
"email TEXT UNIQUE)");
3.2 插入数据
直接执行 SQL
query.exec("INSERT INTO users (name, age, email) VALUES ('Alice', 30, 'alice@example.com')");
使用预处理语句(防 SQL 注入)
query.prepare("INSERT INTO users (name, age, email) VALUES (?, ?, ?)");
query.addBindValue("Bob");
query.addBindValue(25);
query.addBindValue("bob@example.com");
query.exec();
3.3 查询数据
if (query.exec("SELECT id, name, age FROM users WHERE age > 20")) {
while (query.next()) {
int id = query.value(0).toInt();
QString name = query.value("name").toString();
int age = query.value(2).toInt();
qDebug() << "User:" << id << name << age;
}
} else {
qDebug() << "Query error:" << query.lastError().text();
}
3.4 更新与删除数据
// 更新
query.exec("UPDATE users SET age = 31 WHERE name = 'Alice'");
// 删除
query.exec("DELETE FROM users WHERE email IS NULL");
4. 事务处理
通过事务确保多个操作的原子性:
db.transaction(); // 开始事务
QSqlQuery query;
query.exec("UPDATE account SET balance = balance - 100 WHERE id = 1");
query.exec("UPDATE account SET balance = balance + 100 WHERE id = 2");
if (/* 检查操作是否成功 */) {
db.commit(); // 提交事务
} else {
db.rollback(); // 回滚事务
}
5. 使用模型-视图(Model-View)编程
Qt 提供了 QSqlTableModel
和 QSqlQueryModel
,方便将数据库与 UI 组件(如 QTableView
)绑定。
5.1 显示表格数据
QSqlTableModel *model = new QSqlTableModel(this);
model->setTable("users");
model->setFilter("age > 20");
model->select();
QTableView *view = new QTableView;
view->setModel(model);
view->show();
5.2 编辑并保存修改
model->setEditStrategy(QSqlTableModel::OnManualSubmit);
// 用户通过视图修改数据后调用:
model->submitAll(); // 提交所有更改到数据库
6. 错误处理与调试
6.1 捕获数据库错误
if (!query.exec("INVALID SQL")) {
qDebug() << "SQL Error:" << query.lastError().text();
qDebug() << "Executed SQL:" << query.lastQuery();
}
6.2 查看支持的数据库驱动
qDebug() << "Available drivers:" << QSqlDatabase::drivers();
// 输出示例:("QSQLITE", "QMYSQL", "QPSQL")
7. 高级技巧与注意事项
7.1 批量插入优化
使用事务加速大批量插入:
db.transaction();
QSqlQuery query;
query.prepare("INSERT INTO users (name) VALUES (?)");
for (const QString &name : namesList) {
query.addBindValue(name);
query.exec();
}
db.commit();
7.2 多线程访问
-
SQLite 默认不支持多线程同时写入,需通过
QSqlDatabase::cloneDatabase
为每个线程创建独立连接。 -
在子线程中使用数据库时,确保在子线程内打开连接。
7.3 数据库迁移
-
使用
user_version
字段管理数据库版本:query.exec("PRAGMA user_version = 1"); // 设置版本号 query.exec("PRAGMA user_version"); // 读取版本号
8. 常见问题解答
Q1:数据库文件被锁定了怎么办?
-
确保所有
QSqlQuery
和QSqlDatabase
对象在使用后及时释放。 -
避免多线程同时写入同一连接。
Q2:如何防止 SQL 注入?
-
始终使用
prepare()
和addBindValue()
替代字符串拼接。
Q3:查询性能慢如何优化?
-
为常用查询字段添加索引。
-
减少频繁的小事务,合并为批量操作。
9. 完整示例代码
#include <QCoreApplication>
#include <QSqlDatabase>
#include <QSqlQuery>
#include <QDebug>
int main(int argc, char *argv[]) {
QCoreApplication a(argc, argv);
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
db.setDatabaseName("test.db");
if (!db.open()) {
qDebug() << "Database error:" << db.lastError().text();
return -1;
}
QSqlQuery query;
query.exec("CREATE TABLE IF NOT EXISTS books ("
"id INTEGER PRIMARY KEY,"
"title TEXT,"
"author TEXT)");
query.prepare("INSERT INTO books (title, author) VALUES (?, ?)");
query.addBindValue("Qt Programming");
query.addBindValue("John Doe");
query.exec();
query.exec("SELECT * FROM books");
while (query.next()) {
qDebug() << "Book:" << query.value("title").toString()
<< "by" << query.value("author").toString();
}
db.close();
return a.exec();
}
10. 总结
Qt 的 SQLite 支持使得本地数据管理变得简单高效。核心要点包括:
-
使用
QSqlDatabase
管理数据库连接。 -
通过
QSqlQuery
执行 SQL 语句并处理结果。 -
利用事务保证数据一致性。
-
结合模型-视图框架快速构建 UI 界面。
官方文档参考:
-
Qt SQL Module
-
SQLite 官方文档