Qt6实现SQLite数据库的增删改查
Qt6提供了强大的数据库支持,可以方便地实现SQLite数据库的增删改查操作。下面我将详细介绍如何使用Qt6进行SQLite数据库的基本操作。
一、准备工作
1.1 添加数据库模块
在项目文件(.pro)中添加:
QT += sql
1.2 包含头文件
#include <QSqlDatabase>
#include <QSqlQuery>
#include <QSqlError>
#include <QSqlResult>
#include <QDebug>
二、数据库连接
2.1 建立连接
bool createConnection()
{
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
db.setDatabaseName("mydatabase.db"); // 数据库文件名
if (!db.open())
{
qDebug() << "数据库打开失败:" << db.lastError().text(); return false; }
qDebug() << "数据库连接成功"; return true; }
2.2 关闭连接
void closeConnection()
{
QSqlDatabase::database().close();
QSqlDatabase::removeDatabase(QSqlDatabase::defaultConnection);
qDebug() << "数据库连接已关闭";
}
三、创建表
bool createTable() {
QSqlQuery query; // 创建用户表
QString createTableSQL = R"( CREATE TABLE IF NOT EXISTS users ( id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, age INTEGER, email TEXT UNIQUE, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ) )";
if (!query.exec(createTableSQL)) { qDebug() << "创建表失败:" << query.lastError().text(); return false; }
qDebug() << "用户表创建成功或已存在"; return true; }
四、增删改查操作
4.1 插入数据(增)
bool insertUser(const QString &name, int age, const QString &email)
{
QSqlQuery query; // 使用参数化查询防止SQL注入
QString insertSQL = "INSERT INTO users (name, age, email)
VALUES (?, ?, ?)";
query.prepare(insertSQL);
query.addBindValue(name);
query.addBindValue(age);
query.addBindValue(email);
if (!query.exec())
{ qDebug() << "插入数据失败:" << query.lastError().text();
return false;
}
qDebug() << "插入数据成功,ID:" << query.lastInsertId();
return true;
}
4.2 查询数据(查)
4.2.1 查询所有记录
void selectAllUsers()
{ QSqlQuery query("SELECT * FROM users");
while (query.next())
{ int id = query.value("id").toInt();
QString name = query.value("name").toString();
int age = query.value("age").toInt();
QString email = query.value("email").toString();
QDateTime createdAt = query.value("created_at").toDateTime(); qDebug() << "ID:" << id << "Name:" << name << "Age:" << age << "Email:" << email << "Created At:" << createdAt.toString("yyyy-MM-dd hh:mm:ss"); } }
4.2.2 条件查询
void selectUsersByName(const QString &name)
{ QSqlQuery query; query.prepare("SELECT * FROM users WHERE name LIKE ?");
query.addBindValue("%" + name + "%");
if (!query.exec()) { qDebug() << "查询失败:" << query.lastError().text(); return; }
while (query.next()) { // 处理查询结果... } }
4.3 更新数据(改)
bool updateUserAge(int id, int newAge)
{
QSqlQuery query;
query.prepare("UPDATE users SET age = ? WHERE id = ?");
query.addBindValue(newAge);
query.addBindValue(id);
if (!query.exec()) { qDebug() << "更新数据失败:" << query.lastError().text();
return false; }
qDebug() << "更新了" << query.numRowsAffected() << "条记录"; return true; }
4.4 删除数据(删)
bool deleteUser(int id)
{
QSqlQuery query;
query.prepare("DELETE FROM users WHERE id = ?");
query.addBindValue(id);
if (!query.exec()) { qDebug() << "删除数据失败:" << query.lastError().text();
return false;
}
qDebug() << "删除了" << query.numRowsAffected() << "条记录";
return true;
}
五、事务处理
bool performTransaction() {
QSqlDatabase::database().transaction();
QSqlQuery query1, query2;
// 执行第一个操作
if (!query1.exec("INSERT INTO users (name, age) VALUES ('Alice', 25)")) {
QSqlDatabase::database().rollback();
qDebug() << "事务失败:" << query1.lastError().text();
return false;
}
// 执行第二个操作
if (!query2.exec("UPDATE users SET age = 30 WHERE name = 'Bob'")) {
QSqlDatabase::database().rollback();
qDebug() << "事务失败:" << query2.lastError().text();
return false;
}
// 提交事务
QSqlDatabase::database().commit();
qDebug() << "事务执行成功";
return true;
}
六、错误处理
void handleError(const QSqlError &error) {
if (error.isValid()) {
qDebug() << "数据库错误:";
qDebug() << "驱动错误:" << error.driverText();
qDebug() << "数据库错误:" << error.databaseText();
qDebug() << "错误代码:" << error.nativeErrorCode();
}
}
七、完整示例
#include <QCoreApplication>
#include <QtSql>
int main(int argc, char *argv[]) {
QCoreApplication a(argc, argv);
// 1. 建立连接
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
db.setDatabaseName("example.db");
if (!db.open()) {
qDebug() << "数据库打开失败:" << db.lastError().text();
return -1;
}
// 2. 创建表
QSqlQuery query;
if (!query.exec("CREATE TABLE IF NOT EXISTS products ("
"id INTEGER PRIMARY KEY AUTOINCREMENT, "
"name TEXT NOT NULL, "
"price REAL, "
"stock INTEGER)")) {
qDebug() << "创建表失败:" << query.lastError().text();
return -1;
}
// 3. 插入数据
query.prepare("INSERT INTO products (name, price, stock) VALUES (?, ?, ?)");
query.addBindValue("Laptop");
query.addBindValue(999.99);
query.addBindValue(10);
if (!query.exec()) {
qDebug() << "插入数据失败:" << query.lastError().text();
}
// 4. 查询数据
if (query.exec("SELECT * FROM products")) {
while (query.next()) {
int id = query.value(0).toInt();
QString name = query.value(1).toString();
double price = query.value(2).toDouble();
int stock = query.value(3).toInt();
qDebug() << "ID:" << id << "Name:" << name
<< "Price:" << price << "Stock:" << stock;
}
} else {
qDebug() << "查询失败:" << query.lastError().text();
}
// 5. 更新数据
query.prepare("UPDATE products SET price = ? WHERE name = ?");
query.addBindValue(899.99);
query.addBindValue("Laptop");
if (!query.exec()) {
qDebug() << "更新失败:" << query.lastError().text();
}
// 6. 删除数据
query.prepare("DELETE FROM products WHERE stock = 0");
if (!query.exec()) {
qDebug() << "删除失败:" << query.lastError().text();
}
db.close();
return a.exec();
}
八、注意事项
- SQL注入防护:始终使用参数化查询(prepare + addBindValue)而不是字符串拼接
- 错误处理:检查每个数据库操作的返回值并处理错误
- 资源管理:确保数据库连接在使用后正确关闭
- 事务使用:对多个相关操作使用事务保证数据一致性
- 性能考虑:对于大量数据操作,考虑批量处理
- 线程安全:Qt的SQL模块不是线程安全的,每个线程应有自己的连接
通过以上方法,您可以在Qt6应用中高效地实现SQLite数据库的增删改查操作。