一、环境准备
1. 安装 postgresql
确保已安装 postgresql 并创建了测试数据库。
2. 安装 qt 开发环境
确保已安装 qt 开发环境(qt creator 或命令行工具)。
3. 配置 qt 连接 postgresql
在项目文件(.pro)中添加:
qt += sql
二、连接 postgresql 数据库
1. 基本连接方式
#include <qcoreapplication>
#include <qtsql/qsqldatabase>
#include <qtsql/qsqlerror>
#include <qdebug>
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() << "数据库连接失败:" << db.lasterror().text();
return -1;
}
qdebug() << "成功连接到数据库";
// 关闭连接
db.close();
return a.exec();
}2. 使用连接池(推荐)
// 创建连接池
qsqldatabase createconnectionpool(const qstring &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() << "创建连接池失败:" << db.lasterror().text();
return qsqldatabase();
}
return db;
}
// 获取连接
qsqldatabase getconnection(const qstring &connectionname) {
qsqldatabase db = qsqldatabase::database(connectionname);
if (!db.isopen()) {
if (!db.open()) {
qcritical() << "获取连接失败:" << db.lasterror().text();
return qsqldatabase();
}
}
return db;
}
// 释放连接
void releaseconnection(const qstring &connectionname) {
qsqldatabase::removedatabase(connectionname);
}三、实现增删改查操作
1. 创建测试表
首先在 postgresql 中创建测试表:
create table employees (
id serial primary key,
name varchar(100) not null,
position varchar(50),
salary numeric(10, 2),
hire_date date
);2. 插入数据(add)
bool insertemployee(qsqldatabase &db, const qstring &name,
const qstring &position, double salary,
const qdate &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() << "插入数据失败:" << query.lasterror().text();
return false;
}
return true;
}3. 查询数据(query)
3.1 查询单条记录
qsqlrecord getemployeebyid(qsqldatabase &db, int id) {
qsqlquery query(db);
query.prepare("select * from employees where id = :id");
query.bindvalue(":id", id);
if (!query.exec() || !query.next()) {
qdebug() << "查询员工失败:" << query.lasterror().text();
return qsqlrecord();
}
return query.record();
}3.2 查询所有记录
qlist<qsqlrecord> getallemployees(qsqldatabase &db) {
qlist<qsqlrecord> employees;
qsqlquery query(db);
query.exec("select * from employees order by id");
while (query.next()) {
employees.append(query.record());
}
return employees;
}3.3 使用模型查询(qt sql 模型)
qsqltablemodel *createemployeemodel(qobject *parent = nullptr) {
qsqltablemodel *model = new qsqltablemodel(parent);
model->settable("employees");
model->select();
// 设置表头
model->setheaderdata(1, qt::horizontal, tr("name"));
model->setheaderdata(2, qt::horizontal, tr("position"));
model->setheaderdata(3, qt::horizontal, tr("salary"));
model->setheaderdata(4, qt::horizontal, tr("hire date"));
return model;
}4. 更新数据(update)
bool updateemployee(qsqldatabase &db, int id,
const qstring &name, const qstring &position,
double salary, const qdate &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() << "更新员工失败:" << query.lasterror().text();
return false;
}
return true;
}5. 删除数据(delete)
bool deleteemployee(qsqldatabase &db, int id) {
qsqlquery query(db);
query.prepare("delete from employees where id = :id");
query.bindvalue(":id", id);
if (!query.exec()) {
qdebug() << "删除员工失败:" << query.lasterror().text();
return false;
}
return true;
}四、完整示例
1. 使用控制台程序演示crud操作
#include <qcoreapplication>
#include <qtsql/qsqldatabase>
#include <qtsql/qsqlquery>
#include <qtsql/qsqlerror>
#include <qtsql/qsqlrecord>
#include <qdebug>
#include <qdate>
bool opendatabase(qsqldatabase &db) {
db = qsqldatabase::adddatabase("qpsql");
db.sethostname("localhost");
db.setport(5432);
db.setdatabasename("testdb");
db.setusername("postgres");
db.setpassword("password");
if (!db.open()) {
qdebug() << "数据库连接失败:" << db.lasterror().text();
return false;
}
return true;
}
void closedatabase(qsqldatabase &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() << "插入失败:" << query.lasterror().text();
} else {
qdebug() << "插入成功,id:" << query.lastinsertid().toint();
}
// 查询数据
qsqlquery selectquery(db);
selectquery.exec("select * from employees order by id");
while (selectquery.next()) {
qsqlrecord record = selectquery.record();
qdebug() << "id:" << record.value("id").toint()
<< "姓名:" << record.value("name").tostring()
<< "职位:" << record.value("position").tostring()
<< "薪资:" << record.value("salary").todouble()
<< "入职日期:" << 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() << "更新失败:" << query.lasterror().text();
} else {
qdebug() << "更新成功";
}
// 删除数据
query.prepare("delete from employees where id = :id");
query.bindvalue(":id", 1); // 假设要删除id为1的员工
if (!query.exec()) {
qdebug() << "删除失败:" << query.lasterror().text();
} else {
qdebug() << "删除成功";
}
closedatabase(db);
return a.exec();
}2. 使用qt widgets实现gui界面
// employeeform.h
#ifndef employeeform_h
#define employeeform_h
#include <qwidget>
#include <qsqltablemodel>
#include <qdatawidgetmapper>
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 <qsqldatabase>
#include <qsqlerror>
#include <qmessagebox>
employeeform::employeeform(qwidget *parent)
: qwidget(parent)
, ui(new ui::employeeform)
{
ui->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->settable("employees");
model->select();
// 设置表头
model->setheaderdata(1, qt::horizontal, tr("姓名"));
model->setheaderdata(2, qt::horizontal, tr("职位"));
model->setheaderdata(3, qt::horizontal, tr("薪资"));
model->setheaderdata(4, qt::horizontal, tr("入职日期"));
// 设置视图
ui->tableview->setmodel(model);
ui->tableview->setedittriggers(qabstractitemview::doubleclicked);
// 设置数据映射器
mapper = new qdatawidgetmapper(this);
mapper->setmodel(model);
mapper->addmapping(ui->nameedit, 1);
mapper->addmapping(ui->positionedit, 2);
mapper->addmapping(ui->salaryedit, 3);
mapper->addmapping(ui->hiredateedit, 4);
// 连接信号槽
connect(ui->tableview->selectionmodel(), &qitemselectionmodel::currentrowchanged,
this, [this](const qmodelindex ¤t, const qmodelindex &) {
mapper->setcurrentmodelindex(current);
});
}
employeeform::~employeeform()
{
delete ui;
}
void employeeform::on_addbutton_clicked()
{
int row = model->rowcount();
model->insertrow(row);
ui->tableview->selectrow(row);
mapper->setcurrentindex(row);
ui->nameedit->setfocus();
}
void employeeform::on_savebutton_clicked()
{
if (!model->submitall()) {
qmessagebox::warning(this, "错误", "保存失败: " + model->lasterror().text());
} else {
model->database().transaction();
if (model->submitall()) {
model->database().commit();
qmessagebox::information(this, "成功", "数据保存成功");
} else {
model->database().rollback();
qmessagebox::warning(this, "错误", "保存失败: " + model->lasterror().text());
}
}
}
void employeeform::on_deletebutton_clicked()
{
qmodelindex index = ui->tableview->currentindex();
if (index.isvalid()) {
int ret = qmessagebox::question(this, "确认", "确定要删除这条记录吗?",
qmessagebox::yes | qmessagebox::no);
if (ret == qmessagebox::yes) {
model->removerow(index.row());
if (!model->submitall()) {
qmessagebox::warning(this, "错误", "删除失败: " + model->lasterror().text());
model->revertall();
}
}
}
}
void employeeform::on_refreshbutton_clicked()
{
model->select();
}五、高级功能
1. 事务处理
bool performtransaction(qsqldatabase &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;
}2. 批量插入
bool batchinsertemployees(qsqldatabase &db, const qlist<qvariantlist> &employees) {
qsqldatabase::database().transaction();
qsqlquery query(db);
query.prepare("insert into employees (name, position, salary, hire_date) "
"values (?, ?, ?, ?)");
foreach (const qvariantlist &employee, employees) {
query.addbindvalue(employee);
if (!query.execbatch()) {
qsqldatabase::database().rollback();
return false;
}
}
qsqldatabase::database().commit();
return true;
}3. 使用存储过程
bool callstoredprocedure(qsqldatabase &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() << "调用存储过程失败:" << query.lasterror().text();
return false;
}
return true;
}六、常见问题解决
1. 连接失败
- 检查postgresql服务是否运行
- 验证连接参数(主机名、端口、数据库名、用户名、密码)
- 检查防火墙设置
- 确保安装了postgresql客户端库
2. 中文乱码
// 设置编码
qtextcodec::setcodecforlocale(qtextcodec::codecforname("utf-8"));或者在连接字符串中指定编码:
db.setconnectoptions("client_encoding=utf8");3. 性能优化
- 使用预处理语句
- 批量操作代替单条操作
- 合理使用事务
- 为常用查询创建索引
七、总结
qt 提供了强大而灵活的数据库访问功能,通过 qt sql 模块可以轻松实现 postgresql 数据库的增删改查操作。本文介绍了从基本连接到高级功能的实现方法,并提供了完整的代码示例。在实际开发中,可以根据项目需求选择合适的实现方式,结合事务处理、批量操作等技术提高应用性能。
以上就是qt操作postgresql数据库并实现增删改查功能的详细内容,更多关于qt操作postgresql增删改查的资料请关注代码网其它相关文章!
发表评论