月配音 發表於 2025-5-15 08:58:08

QT操作PostgreSQL数据库并实现增删改查功能

<div id="navCategory"><h5 class="catalogue">目录</h5><ul class="first_class_ul"><li><a href="#_label0">一、环境准备</a></li><ul class="second_class_ul"><li><a href="#_lab2_0_0">1. 安装 PostgreSQL</a></li><li><a href="#_lab2_0_1">2. 安装 Qt 开发环境</a></li><li><a href="#_lab2_0_2">3. 配置 Qt 连接 PostgreSQL</a></li></ul><li><a href="#_label1">二、连接 PostgreSQL 数据库</a></li><ul class="second_class_ul"><li><a href="#_lab2_1_3">1. 基本连接方式</a></li><li><a href="#_lab2_1_4">2. 使用连接池(推荐)</a></li></ul><li><a href="#_label2">三、实现增删改查操作</a></li><ul class="second_class_ul"><li><a href="#_lab2_2_5">1. 创建测试表</a></li><li><a href="#_lab2_2_6">2. 插入数据(Add)</a></li><li><a href="#_lab2_2_7">3. 查询数据(Query)</a></li><ul class="third_class_ul"><li><a href="#_label3_2_7_0">3.1 查询单条记录</a></li><li><a href="#_label3_2_7_1">3.2 查询所有记录</a></li><li><a href="#_label3_2_7_2">3.3 使用模型查询(Qt SQL 模型)</a></li></ul><li><a href="#_lab2_2_8">4. 更新数据(Update)</a></li><ul class="third_class_ul"></ul><li><a href="#_lab2_2_9">5. 删除数据(Delete)</a></li><ul class="third_class_ul"></ul></ul><li><a href="#_label3">四、完整示例</a></li><ul class="second_class_ul"><li><a href="#_lab2_3_10">1. 使用控制台程序演示CRUD操作</a></li><ul class="third_class_ul"></ul><li><a href="#_lab2_3_11">2. 使用Qt Widgets实现GUI界面</a></li><ul class="third_class_ul"></ul></ul><li><a href="#_label4">五、高级功能</a></li><ul class="second_class_ul"><li><a href="#_lab2_4_12">1. 事务处理</a></li><ul class="third_class_ul"></ul><li><a href="#_lab2_4_13">2. 批量插入</a></li><ul class="third_class_ul"></ul><li><a href="#_lab2_4_14">3. 使用存储过程</a></li><ul class="third_class_ul"></ul></ul><li><a href="#_label5">六、常见问题解决</a></li><ul class="second_class_ul"><li><a href="#_lab2_5_15">1. 连接失败</a></li><ul class="third_class_ul"></ul><li><a href="#_lab2_5_16">2. 中文乱码</a></li><ul class="third_class_ul"></ul><li><a href="#_lab2_5_17">3. 性能优化</a></li><ul class="third_class_ul"></ul></ul><li><a href="#_label6">七、总结</a></li><ul class="second_class_ul"></ul></ul></div><p class="maodian"><a name="_label0"></a></p><h2>一、环境准备</h2>
<p class="maodian"><a name="_lab2_0_0"></a></p><h3>1. 安装 PostgreSQL</h3>
<p>确保已安装 PostgreSQL 并创建了测试数据库。</p>
<p class="maodian"><a name="_lab2_0_1"></a></p><h3>2. 安装 Qt 开发环境</h3>
<p>确保已安装 Qt 开发环境(Qt Creator 或命令行工具)。</p>
<p class="maodian"><a name="_lab2_0_2"></a></p><h3>3. 配置 Qt 连接 PostgreSQL</h3>
<p>在项目文件(.pro)中添加:</p>
<div class="jb51code"><pre class="brush:cpp;">QT += sql</pre></div>
<p class="maodian"><a name="_label1"></a></p><h2>二、连接 PostgreSQL 数据库</h2>
<p class="maodian"><a name="_lab2_1_3"></a></p><h3>1. 基本连接方式</h3>
<div class="jb51code"><pre class="brush:cpp;">#include &lt;QCoreApplication&gt;
#include &lt;QtSql/QSqlDatabase&gt;
#include &lt;QtSql/QSqlError&gt;
#include &lt;QDebug&gt;

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
   
    // 创建数据库连接
    QSqlDatabase db = QSqlDatabase::addDatabase("QPSQL");
   
    // 设置连接参数
    db.setHostName("localhost");      // 主机名
    db.setPort(5432);               // 端口
    db.setDatabaseName("testdb");   // 数据库名
    db.setUserName("postgres");       // 用户名
    db.setPassword("password");       // 密码
   
    // 打开连接
    if (!db.open()) {
      qDebug() &lt;&lt; "数据库连接失败:" &lt;&lt; db.lastError().text();
      return -1;
    }
   
    qDebug() &lt;&lt; "成功连接到数据库";
   
    // 关闭连接
    db.close();
   
    return a.exec();
}</pre></div>
<p class="maodian"><a name="_lab2_1_4"></a></p><h3>2. 使用连接池(推荐)</h3>
<div class="jb51code"><pre class="brush:cpp;">// 创建连接池
QSqlDatabase createConnectionPool(const QString &amp;connectionName) {
    QSqlDatabase db = QSqlDatabase::addDatabase("QPSQL", connectionName);
    db.setHostName("localhost");
    db.setPort(5432);
    db.setDatabaseName("testdb");
    db.setUserName("postgres");
    db.setPassword("password");
   
    if (!db.open()) {
      qCritical() &lt;&lt; "创建连接池失败:" &lt;&lt; db.lastError().text();
      return QSqlDatabase();
    }
   
    return db;
}

// 获取连接
QSqlDatabase getConnection(const QString &amp;connectionName) {
    QSqlDatabase db = QSqlDatabase::database(connectionName);
    if (!db.isOpen()) {
      if (!db.open()) {
            qCritical() &lt;&lt; "获取连接失败:" &lt;&lt; db.lastError().text();
            return QSqlDatabase();
      }
    }
    return db;
}

// 释放连接
void releaseConnection(const QString &amp;connectionName) {
    QSqlDatabase::removeDatabase(connectionName);
}</pre></div>
<p class="maodian"><a name="_label2"></a></p><h2>三、实现增删改查操作</h2>
<p class="maodian"><a name="_lab2_2_5"></a></p><h3>1. 创建测试表</h3>
<p>首先在 PostgreSQL 中创建测试表:</p>
<div class="jb51code"><pre class="brush:sql;">CREATE TABLE employees (
    id SERIAL PRIMARY KEY,
    name VARCHAR(100) NOT NULL,
    position VARCHAR(50),
    salary NUMERIC(10, 2),
    hire_date DATE
);</pre></div>
<p class="maodian"><a name="_lab2_2_6"></a></p><h3>2. 插入数据(Add)</h3>
<div class="jb51code"><pre class="brush:cpp;">bool insertEmployee(QSqlDatabase &amp;db, const QString &amp;name,
                  const QString &amp;position, double salary,
                  const QDate &amp;hireDate) {
    QSqlQuery query(db);
   
    // 使用预处理语句防止SQL注入
    query.prepare("INSERT INTO employees (name, position, salary, hire_date) "
                  "VALUES (:name, :position, :salary, :hire_date)");
   
    query.bindValue(":name", name);
    query.bindValue(":position", position);
    query.bindValue(":salary", salary);
    query.bindValue(":hire_date", hireDate);
   
    if (!query.exec()) {
      qDebug() &lt;&lt; "插入数据失败:" &lt;&lt; query.lastError().text();
      return false;
    }
   
    return true;
}</pre></div>
<p class="maodian"><a name="_lab2_2_7"></a></p><h3>3. 查询数据(Query)</h3>
<p class="maodian"><a name="_label3_2_7_0"></a></p><h4>3.1 查询单条记录</h4>
<div class="jb51code"><pre class="brush:cpp;">QSqlRecord getEmployeeById(QSqlDatabase &amp;db, int id) {
    QSqlQuery query(db);
    query.prepare("SELECT * FROM employees WHERE id = :id");
    query.bindValue(":id", id);
   
    if (!query.exec() || !query.next()) {
      qDebug() &lt;&lt; "查询员工失败:" &lt;&lt; query.lastError().text();
      return QSqlRecord();
    }
   
    return query.record();
}</pre></div>
<p class="maodian"><a name="_label3_2_7_1"></a></p><h4>3.2 查询所有记录</h4>
<div class="jb51code"><pre class="brush:cpp;">QList&lt;QSqlRecord&gt; getAllEmployees(QSqlDatabase &amp;db) {
    QList&lt;QSqlRecord&gt; employees;
    QSqlQuery query(db);
    query.exec("SELECT * FROM employees ORDER BY id");
   
    while (query.next()) {
      employees.append(query.record());
    }
   
    return employees;
}</pre></div>
<p class="maodian"><a name="_label3_2_7_2"></a></p><h4>3.3 使用模型查询(Qt SQL 模型)</h4>
<div class="jb51code"><pre class="brush:cpp;">QSqlTableModel *createEmployeeModel(QObject *parent = nullptr) {
    QSqlTableModel *model = new QSqlTableModel(parent);
    model-&gt;setTable("employees");
    model-&gt;select();
   
    // 设置表头
    model-&gt;setHeaderData(1, Qt::Horizontal, tr("Name"));
    model-&gt;setHeaderData(2, Qt::Horizontal, tr("Position"));
    model-&gt;setHeaderData(3, Qt::Horizontal, tr("Salary"));
    model-&gt;setHeaderData(4, Qt::Horizontal, tr("Hire Date"));
   
    return model;
}</pre></div>
<p class="maodian"><a name="_lab2_2_8"></a></p><h3>4. 更新数据(Update)</h3>
<div class="jb51code"><pre class="brush:cpp;">bool updateEmployee(QSqlDatabase &amp;db, int id,
                  const QString &amp;name, const QString &amp;position,
                  double salary, const QDate &amp;hireDate) {
    QSqlQuery query(db);
    query.prepare("UPDATE employees SET name = :name, position = :position, "
                  "salary = :salary, hire_date = :hire_date WHERE id = :id");
   
    query.bindValue(":name", name);
    query.bindValue(":position", position);
    query.bindValue(":salary", salary);
    query.bindValue(":hire_date", hireDate);
    query.bindValue(":id", id);
   
    if (!query.exec()) {
      qDebug() &lt;&lt; "更新员工失败:" &lt;&lt; query.lastError().text();
      return false;
    }
   
    return true;
}</pre></div>
<p class="maodian"><a name="_lab2_2_9"></a></p><h3>5. 删除数据(Delete)</h3>
<div class="jb51code"><pre class="brush:cpp;">bool deleteEmployee(QSqlDatabase &amp;db, int id) {
    QSqlQuery query(db);
    query.prepare("DELETE FROM employees WHERE id = :id");
    query.bindValue(":id", id);
   
    if (!query.exec()) {
      qDebug() &lt;&lt; "删除员工失败:" &lt;&lt; query.lastError().text();
      return false;
    }
   
    return true;
}</pre></div>
<p class="maodian"><a name="_label3"></a></p><h2>四、完整示例</h2>
<p class="maodian"><a name="_lab2_3_10"></a></p><h3>1. 使用控制台程序演示CRUD操作</h3>
<div class="jb51code"><pre class="brush:cpp;">#include &lt;QCoreApplication&gt;
#include &lt;QtSql/QSqlDatabase&gt;
#include &lt;QtSql/QSqlQuery&gt;
#include &lt;QtSql/QSqlError&gt;
#include &lt;QtSql/QSqlRecord&gt;
#include &lt;QDebug&gt;
#include &lt;QDate&gt;

bool openDatabase(QSqlDatabase &amp;db) {
    db = QSqlDatabase::addDatabase("QPSQL");
    db.setHostName("localhost");
    db.setPort(5432);
    db.setDatabaseName("testdb");
    db.setUserName("postgres");
    db.setPassword("password");
   
    if (!db.open()) {
      qDebug() &lt;&lt; "数据库连接失败:" &lt;&lt; db.lastError().text();
      return false;
    }
    return true;
}

void closeDatabase(QSqlDatabase &amp;db) {
    db.close();
}

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
   
    QSqlDatabase db;
    if (!openDatabase(db)) {
      return -1;
    }
   
    // 插入数据
    QSqlQuery query(db);
    query.prepare("INSERT INTO employees (name, position, salary, hire_date) "
                  "VALUES (:name, :position, :salary, :hire_date)");
   
    query.bindValue(":name", "张三");
    query.bindValue(":position", "开发工程师");
    query.bindValue(":salary", 15000.00);
    query.bindValue(":hire_date", QDate::currentDate());
   
    if (!query.exec()) {
      qDebug() &lt;&lt; "插入失败:" &lt;&lt; query.lastError().text();
    } else {
      qDebug() &lt;&lt; "插入成功,ID:" &lt;&lt; query.lastInsertId().toInt();
    }
   
    // 查询数据
    QSqlQuery selectQuery(db);
    selectQuery.exec("SELECT * FROM employees ORDER BY id");
   
    while (selectQuery.next()) {
      QSqlRecord record = selectQuery.record();
      qDebug() &lt;&lt; "ID:" &lt;&lt; record.value("id").toInt()
               &lt;&lt; "姓名:" &lt;&lt; record.value("name").toString()
               &lt;&lt; "职位:" &lt;&lt; record.value("position").toString()
               &lt;&lt; "薪资:" &lt;&lt; record.value("salary").toDouble()
               &lt;&lt; "入职日期:" &lt;&lt; record.value("hire_date").toDate();
    }
   
    // 更新数据
    query.prepare("UPDATE employees SET salary = :salary WHERE id = :id");
    query.bindValue(":salary", 16000.00);
    query.bindValue(":id", 1); // 假设ID为1的员工
   
    if (!query.exec()) {
      qDebug() &lt;&lt; "更新失败:" &lt;&lt; query.lastError().text();
    } else {
      qDebug() &lt;&lt; "更新成功";
    }
   
    // 删除数据
    query.prepare("DELETE FROM employees WHERE id = :id");
    query.bindValue(":id", 1); // 假设要删除ID为1的员工
   
    if (!query.exec()) {
      qDebug() &lt;&lt; "删除失败:" &lt;&lt; query.lastError().text();
    } else {
      qDebug() &lt;&lt; "删除成功";
    }
   
    closeDatabase(db);
    return a.exec();
}</pre></div>
<p class="maodian"><a name="_lab2_3_11"></a></p><h3>2. 使用Qt Widgets实现GUI界面</h3>
<div class="jb51code"><pre class="brush:cpp;">// employeeform.h
#ifndef EMPLOYEEFORM_H
#define EMPLOYEEFORM_H

#include &lt;QWidget&gt;
#include &lt;QSqlTableModel&gt;
#include &lt;QDataWidgetMapper&gt;

QT_BEGIN_NAMESPACE
namespace Ui { class EmployeeForm; }
QT_END_NAMESPACE

class EmployeeForm : public QWidget
{
    Q_OBJECT

public:
    EmployeeForm(QWidget *parent = nullptr);
    ~EmployeeForm();

private slots:
    void on_addButton_clicked();
    void on_saveButton_clicked();
    void on_deleteButton_clicked();
    void on_refreshButton_clicked();

private:
    Ui::EmployeeForm *ui;
    QSqlTableModel *model;
    QDataWidgetMapper *mapper;
};

#endif // EMPLOYEEFORM_H

// employeeform.cpp
#include "employeeform.h"
#include "ui_employeeform.h"
#include &lt;QSqlDatabase&gt;
#include &lt;QSqlError&gt;
#include &lt;QMessageBox&gt;

EmployeeForm::EmployeeForm(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::EmployeeForm)
{
    ui-&gt;setupUi(this);

    // 连接数据库
    QSqlDatabase db = QSqlDatabase::addDatabase("QPSQL");
    db.setHostName("localhost");
    db.setPort(5432);
    db.setDatabaseName("testdb");
    db.setUserName("postgres");
    db.setPassword("password");

    if (!db.open()) {
      QMessageBox::critical(this, "错误", "无法连接到数据库: " + db.lastError().text());
      return;
    }

    // 创建模型
    model = new QSqlTableModel(this, db);
    model-&gt;setTable("employees");
    model-&gt;select();

    // 设置表头
    model-&gt;setHeaderData(1, Qt::Horizontal, tr("姓名"));
    model-&gt;setHeaderData(2, Qt::Horizontal, tr("职位"));
    model-&gt;setHeaderData(3, Qt::Horizontal, tr("薪资"));
    model-&gt;setHeaderData(4, Qt::Horizontal, tr("入职日期"));

    // 设置视图
    ui-&gt;tableView-&gt;setModel(model);
    ui-&gt;tableView-&gt;setEditTriggers(QAbstractItemView::DoubleClicked);

    // 设置数据映射器
    mapper = new QDataWidgetMapper(this);
    mapper-&gt;setModel(model);
    mapper-&gt;addMapping(ui-&gt;nameEdit, 1);
    mapper-&gt;addMapping(ui-&gt;positionEdit, 2);
    mapper-&gt;addMapping(ui-&gt;salaryEdit, 3);
    mapper-&gt;addMapping(ui-&gt;hireDateEdit, 4);

    // 连接信号槽
    connect(ui-&gt;tableView-&gt;selectionModel(), &amp;QItemSelectionModel::currentRowChanged,
            this, (const QModelIndex &amp;current, const QModelIndex &amp;) {
                mapper-&gt;setCurrentModelIndex(current);
            });
}

EmployeeForm::~EmployeeForm()
{
    delete ui;
}

void EmployeeForm::on_addButton_clicked()
{
    int row = model-&gt;rowCount();
    model-&gt;insertRow(row);
    ui-&gt;tableView-&gt;selectRow(row);
    mapper-&gt;setCurrentIndex(row);
    ui-&gt;nameEdit-&gt;setFocus();
}

void EmployeeForm::on_saveButton_clicked()
{
    if (!model-&gt;submitAll()) {
      QMessageBox::warning(this, "错误", "保存失败: " + model-&gt;lastError().text());
    } else {
      model-&gt;database().transaction();
      if (model-&gt;submitAll()) {
            model-&gt;database().commit();
            QMessageBox::information(this, "成功", "数据保存成功");
      } else {
            model-&gt;database().rollback();
            QMessageBox::warning(this, "错误", "保存失败: " + model-&gt;lastError().text());
      }
    }
}

void EmployeeForm::on_deleteButton_clicked()
{
    QModelIndex index = ui-&gt;tableView-&gt;currentIndex();
    if (index.isValid()) {
      int ret = QMessageBox::question(this, "确认", "确定要删除这条记录吗?",
                                        QMessageBox::Yes | QMessageBox::No);
      if (ret == QMessageBox::Yes) {
            model-&gt;removeRow(index.row());
            if (!model-&gt;submitAll()) {
                QMessageBox::warning(this, "错误", "删除失败: " + model-&gt;lastError().text());
                model-&gt;revertAll();
            }
      }
    }
}

void EmployeeForm::on_refreshButton_clicked()
{
    model-&gt;select();
}</pre></div>
<p class="maodian"><a name="_label4"></a></p><h2>五、高级功能</h2>
<p class="maodian"><a name="_lab2_4_12"></a></p><h3>1. 事务处理</h3>
<div class="jb51code"><pre class="brush:cpp;">bool performTransaction(QSqlDatabase &amp;db) {
    db.transaction();
   
    QSqlQuery query(db);
    bool success = true;
   
    // 执行多个操作
    if (!query.exec("INSERT INTO employees (...) VALUES (...)" )) {
      success = false;
    }
   
    if (!query.exec("UPDATE ...")) {
      success = false;
    }
   
    if (success) {
      db.commit();
    } else {
      db.rollback();
    }
   
    return success;
}</pre></div>
<p class="maodian"><a name="_lab2_4_13"></a></p><h3>2. 批量插入</h3>
<div class="jb51code"><pre class="brush:cpp;">bool batchInsertEmployees(QSqlDatabase &amp;db, const QList&lt;QVariantList&gt; &amp;employees) {
    QSqlDatabase::database().transaction();
   
    QSqlQuery query(db);
    query.prepare("INSERT INTO employees (name, position, salary, hire_date) "
                  "VALUES (?, ?, ?, ?)");
   
    foreach (const QVariantList &amp;employee, employees) {
      query.addBindValue(employee);
      if (!query.execBatch()) {
            QSqlDatabase::database().rollback();
            return false;
      }
    }
   
    QSqlDatabase::database().commit();
    return true;
}</pre></div>
<p class="maodian"><a name="_lab2_4_14"></a></p><h3>3. 使用存储过程</h3>
<div class="jb51code"><pre class="brush:cpp;">bool callStoredProcedure(QSqlDatabase &amp;db, int employeeId) {
    QSqlQuery query(db);
    query.prepare("CALL update_employee_salary(:id, :percentage)");
    query.bindValue(":id", employeeId);
    query.bindValue(":percentage", 10); // 增加10%
   
    if (!query.exec()) {
      qDebug() &lt;&lt; "调用存储过程失败:" &lt;&lt; query.lastError().text();
      return false;
    }
   
    return true;
}</pre></div>
<p class="maodian"><a name="_label5"></a></p><h2>六、常见问题解决</h2>
<p class="maodian"><a name="_lab2_5_15"></a></p><h3>1. 连接失败</h3>
<ul><li>检查PostgreSQL服务是否运行</li><li>验证连接参数(主机名、端口、数据库名、用户名、密码)</li><li>检查防火墙设置</li><li>确保安装了PostgreSQL客户端库</li></ul>
<p class="maodian"><a name="_lab2_5_16"></a></p><h3>2. 中文乱码</h3>
<div class="jb51code"><pre class="brush:cpp;">// 设置编码
QTextCodec::setCodecForLocale(QTextCodec::codecForName("UTF-8"));</pre></div>
<p>或者在连接字符串中指定编码:</p>
<div class="jb51code"><pre class="brush:cpp;">db.setConnectOptions("client_encoding=UTF8");</pre></div>
<p class="maodian"><a name="_lab2_5_17"></a></p><h3>3. 性能优化</h3>
<ul><li>使用预处理语句</li><li>批量操作代替单条操作</li><li>合理使用事务</li><li>为常用查询创建索引</li></ul>
<p class="maodian"><a name="_label6"></a></p><h2>七、总结</h2>
<p>Qt 提供了强大而灵活的数据库访问功能,通过 Qt SQL 模块可以轻松实现 PostgreSQL 数据库的增删改查操作。本文介绍了从基本连接到高级功能的实现方法,并提供了完整的代码示例。在实际开发中,可以根据项目需求选择合适的实现方式,结合事务处理、批量操作等技术提高应用性能。</p>
<p>以上就是QT操作PostgreSQL数据库并实现增删改查功能的详细内容,更多关于QT操作PostgreSQL增删改查的资料请关注琼殿技术社区其它相关文章!</p>
頁: [1]
查看完整版本: QT操作PostgreSQL数据库并实现增删改查功能