Qt 数据库编程入门:连接与操作数据库

发布于:2025-07-24 ⋅ 阅读:(37) ⋅ 点赞:(0)

一、Qt数据库模块概述

Qt提供了Qt SQL模块,用于数据库编程。该模块支持多种数据库系统,包括MySQL、PostgreSQL、SQLite、Oracle等,通过统一的API接口进行操作,实现了数据库操作的抽象化。

1.1 主要类介绍

  • QSqlDatabase:管理数据库连接
  • QSqlQuery:执行SQL语句
  • QSqlTableModel:操作单个数据库表的高级接口
  • QSqlRelationalTableModel:支持外键的表模型
  • QSqlQueryModel:只读的查询结果模型
  • QSqlError:提供数据库错误信息

1.2 数据库驱动

Qt通过驱动插件支持不同的数据库系统,常用驱动包括:

  • QSQLITE:SQLite数据库
  • QMYSQL:MySQL数据库
  • QPSQL:PostgreSQL数据库
  • QODBC:ODBC接口(可连接多种数据库)

二、连接数据库

2.1 连接SQLite数据库

SQLite是轻量级嵌入式数据库,无需单独的服务器进程,适合小型应用。

示例:连接SQLite数据库

#include <QSqlDatabase>
#include <QSqlError>
#include <QDebug>

bool connectToDatabase()
{
    QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
    db.setDatabaseName("mydatabase.db");
    
    if (!db.open()) {
        qDebug() << "Cannot open database:" << db.lastError().text();
        return false;
    }
    
    qDebug() << "Database connected successfully";
    return true;
}

2.2 连接MySQL数据库

MySQL是常用的开源关系型数据库,需要安装服务器并创建数据库。

示例:连接MySQL数据库

bool connectToMySQLDatabase()
{
    QSqlDatabase db = QSqlDatabase::addDatabase("QMYSQL");
    db.setHostName("localhost");
    db.setDatabaseName("mydatabase");
    db.setUserName("username");
    db.setPassword("password");
    db.setPort(3306);
    
    if (!db.open()) {
        qDebug() << "Cannot open database:" << db.lastError().text();
        return false;
    }
    
    qDebug() << "MySQL database connected successfully";
    return true;
}

2.3 多数据库连接

可以同时连接多个数据库,每个连接需要指定唯一的连接名。

示例:多数据库连接

// 第一个连接
QSqlDatabase db1 = QSqlDatabase::addDatabase("QSQLITE", "Connection1");
db1.setDatabaseName("database1.db");
db1.open();

// 第二个连接
QSqlDatabase db2 = QSqlDatabase::addDatabase("QSQLITE", "Connection2");
db2.setDatabaseName("database2.db");
db2.open();

// 使用特定连接的查询
QSqlQuery query1(db1);
QSqlQuery query2(db2);

三、执行SQL查询

3.1 使用QSqlQuery执行简单查询

QSqlQuery用于执行SQL语句并处理结果。

示例:创建表

QSqlQuery query;
query.exec("CREATE TABLE IF NOT EXISTS persons ("
           "id INTEGER PRIMARY KEY AUTOINCREMENT, "
           "name TEXT, "
           "age INTEGER)");

if (query.lastError().isValid()) {
    qDebug() << "Error creating table:" << query.lastError().text();
}

示例:插入数据

// 方法1:直接执行SQL
query.exec("INSERT INTO persons (name, age) VALUES ('John', 30)");

// 方法2:使用预处理语句(更安全,防止SQL注入)
query.prepare("INSERT INTO persons (name, age) VALUES (:name, :age)");
query.bindValue(":name", "Alice");
query.bindValue(":age", 25);
query.exec();

示例:查询数据

query.exec("SELECT * FROM persons");
while (query.next()) {
    int id = query.value(0).toInt();
    QString name = query.value(1).toString();
    int age = query.value(2).toInt();
    
    qDebug() << "ID:" << id << "Name:" << name << "Age:" << age;
}

3.2 使用事务处理

事务可以确保一组操作要么全部成功,要么全部失败。

示例:使用事务

QSqlDatabase::database().transaction(); // 开始事务

QSqlQuery query;
query.exec("INSERT INTO persons (name, age) VALUES ('Bob', 35)");
query.exec("INSERT INTO persons (name, age) VALUES ('Charlie', 40)");

if (query.lastError().isValid()) {
    QSqlDatabase::database().rollback(); // 回滚事务
    qDebug() << "Transaction failed:" << query.lastError().text();
} else {
    QSqlDatabase::database().commit(); // 提交事务
    qDebug() << "Transaction succeeded";
}

四、使用模型视图类操作数据库

Qt提供了高级的模型视图类,使数据库操作更加便捷。

4.1 QSqlTableModel

用于操作单个数据库表的读写模型。

示例:使用QSqlTableModel

#include <QSqlTableModel>
#include <QTableView>

// 创建模型
QSqlTableModel *model = new QSqlTableModel(this);
model->setTable("persons");
model->setEditStrategy(QSqlTableModel::OnManualSubmit); // 手动提交更改

// 加载数据
if (!model->select()) {
    qDebug() << "Error loading data:" << model->lastError().text();
}

// 显示在表格视图中
QTableView *view = new QTableView;
view->setModel(model);
view->show();

// 修改数据
model->insertRow(model->rowCount());
model->setData(model->index(model->rowCount()-1, 1), "David");
model->setData(model->index(model->rowCount()-1, 2), 28);

// 提交更改
if (!model->submitAll()) {
    qDebug() << "Error submitting changes:" << model->lastError().text();
}

4.2 QSqlRelationalTableModel

支持外键关联的表模型。

示例:使用QSqlRelationalTableModel

// 假设我们有两个表:departments和employees
// employees表中有一个department_id字段,关联到departments表的id字段

QSqlRelationalTableModel *model = new QSqlRelationalTableModel(this);
model->setTable("employees");
model->setRelation(2, QSqlRelation("departments", "id", "name")); // 设置外键关系

model->setHeaderData(0, Qt::Horizontal, "ID");
model->setHeaderData(1, Qt::Horizontal, "Name");
model->setHeaderData(2, Qt::Horizontal, "Department");

if (!model->select()) {
    qDebug() << "Error loading data:" << model->lastError().text();
}

QTableView *view = new QTableView;
view->setModel(model);
view->show();

五、错误处理

数据库操作可能会失败,必须进行错误检查。

示例:错误处理

QSqlQuery query;
if (!query.exec("SELECT * FROM non_existent_table")) {
    QSqlError error = query.lastError();
    qDebug() << "Query error:" << error.text();
    qDebug() << "Error type:" << error.type();
    qDebug() << "Error number:" << error.number();
}

六、SQLite数据库示例应用

下面是一个完整的SQLite数据库操作示例,包括创建表、插入数据、查询数据和使用模型视图显示数据。

#include <QApplication>
#include <QSqlDatabase>
#include <QSqlQuery>
#include <QSqlError>
#include <QSqlTableModel>
#include <QTableView>
#include <QDebug>

bool createConnection()
{
    QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
    db.setDatabaseName("example.db");
    
    if (!db.open()) {
        qDebug() << "Cannot open database:" << db.lastError().text();
        return false;
    }
    
    // 创建表
    QSqlQuery query;
    query.exec("CREATE TABLE IF NOT EXISTS contacts ("
               "id INTEGER PRIMARY KEY AUTOINCREMENT, "
               "name TEXT, "
               "phone TEXT, "
               "email TEXT)");
    
    if (query.lastError().isValid()) {
        qDebug() << "Error creating table:" << query.lastError().text();
        return false;
    }
    
    return true;
}

void insertSampleData()
{
    QSqlQuery query;
    query.prepare("INSERT INTO contacts (name, phone, email) VALUES (:name, :phone, :email)");
    
    // 插入示例数据
    query.bindValue(":name", "John Doe");
    query.bindValue(":phone", "123-456-7890");
    query.bindValue(":email", "john@example.com");
    query.exec();
    
    query.bindValue(":name", "Jane Smith");
    query.bindValue(":phone", "098-765-4321");
    query.bindValue(":email", "jane@example.com");
    query.exec();
}

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    
    if (!createConnection())
        return 1;
    
    insertSampleData();
    
    // 使用模型视图显示数据
    QSqlTableModel model;
    model.setTable("contacts");
    model.select();
    
    QTableView view;
    view.setModel(&model);
    view.resize(600, 400);
    view.show();
    
    return a.exec();
}

七、总结

Qt SQL模块提供了强大而灵活的数据库编程功能,通过统一的API可以连接和操作多种数据库系统。QSqlDatabase类用于管理数据库连接,QSqlQuery类用于执行SQL语句,而模型视图类(如QSqlTableModel和QSqlRelationalTableModel)则提供了更高级的数据库操作方式。在实际开发中,应根据具体需求选择合适的数据库系统和操作方式,并注意错误处理和事务管理。掌握Qt数据库编程技术,可以开发出数据驱动的应用程序,实现数据的存储、查询和管理功能。