PostgreSQL C++客户端API libpqxx的使用

      PostgreSQL是一个先进的、开源的、免费的、功能强大的关系型数据库,缩写版是postgres。它使用一种客户端/服务器(C/S)的模型。一次PostgreSQL会话由下列相关的进程(程序)组成:

      (1).一个服务器进程,它管理数据库文件、接受来自客户端应用与数据库的连接并且代表客户端在数据库上执行操作。该数据库服务器程序叫做postgres。

      (2).那些需要执行数据库操作的用户的客户端(前端)应用。客户端应用可能本身就是多种多样的:可以是一个面向文本的工具,也可以是一个图形界面的应用,或者是一个通过访问数据库来显示网页的网页服务器,或者是一个特制的数据库管理工具。

      和典型的客户端/服务器应用一样,这些客户端和服务器可以在不同的主机上。这时它们通过TCP/IP网络连接通讯

      PostgreSQL服务器可以处理来自客户端的多个并发请求。因此,它为每个连接启动("forks")一个新的进程。从这个时候开始,客户端和新服务器进程就不再经过最初的postgres进程的干涉进行通讯。因此,守护者服务器进程总是在运行并等待着客户端连接,而客户端和相关联的服务器进程则是起起停停。

      一台运行着的PostgreSQL服务器可以管理许多数据库。通常我们会为每个项目和每个用户单独使用一个数据库。

      libpqxx是PostgreSQL的官方C++客户端API,源码地址:https://github.com/jtv/libpqxx,最新发布版本为7.9.2,license为BSD-3-Clause。

      Windows10上使用CMake编译libpqxx:

      1.build.sh脚本内容如下:

#! /bin/bashif [ $# != 2 ]; thenecho "Error: requires two parameters: 1: dynamic or static; 2: Relese or Debug"echo "For example: dynamic library, debug mode: $0  dynamic Debug"exit -1
fiif [ $1 != "dynamic" ] && [ $1 != "static" ]; thenecho "Error: the first parameter can only be dynamic or static"exit -1
fiif [ $2 != "Release"  ] && [ $2 != "Debug" ]; thenecho "Error: the second parameter can only be Release or Debug"exit -1
fiif [[ ! -d "build" ]]; thenmkdir buildcd build
elsecd build
fidynamic_flag=ON
if [ $1 != "dynamic" ]; thendynamic_flag=OFF
fiecho "build: $1 $2"# vs2022, PostgreSQL 16.4cmake \-G"Visual Studio 17 2022" -A x64 \-DPostgreSQL_ROOT="D:/ProgramFiles/PostgreSQL/16" \-DCMAKE_BUILD_TYPE=$2 \-DCMAKE_CONFIGURATION_TYPES=$2 \-DBUILD_SHARED_LIBS=${dynamic_flag} \-DCMAKE_INSTALL_PREFIX=./install \..
make -j2
cmake --build . --target install --config $2

      2.注意:

      (1).编译libpqxx需要安装PostgreSQL,参考:https://blog.csdn.net/fengbingchun/article/details/141750748,或者至少需要安装用于客户端开发的C头文件和库。库libpqxx建立在PostgreSQL的标准C API libpq之上。

      (2).7.x版本至少需要C++17,对于8.x至少需要C++20。

      (3).推荐:windows上使用动态库,其它平台使用静态库。

      以下为测试代码段:

      (1).创建数据库:

int create_database(const std::string& dbname)
{try {pqxx::connection c{ options + "postgres" }; // database postgres must already existc.set_client_encoding("GBK");pqxx::nontransaction tx{ c };const std::string str{ "CREATE DATABASE " };tx.exec(str + dbname);}catch (const std::exception& e) {std::cerr << "Error:create database: " << e.what() << std::endl;outfile << "Error:create database: " << e.what() << std::endl;return -1;}return 0;
}

      (2).连接数据库:

int connect_database(const std::string& dbname)
{try {pqxx::connection c{ options + dbname };//c.set_client_encoding("GBK"); // GBK, default:UTF8if (c.is_open())std::cout << c.dbname() << " database was opened successfully" << std::endl;else {std::cerr << "Error:failed to open database:" << dbname << std::endl;return -1;}std::cout << "dbname:" << c.dbname() << ", username:" << c.username()<< ", hostname:" << c.hostname() << ", port:" << c.port()<< ", backendpid:" << c.backendpid() << ", sock:" << c.sock()<< ", protocol_version:" << c.protocol_version()<< ", server_version:" << c.server_version()<< ", get_client_encoding:" << c.get_client_encoding()<< ", encoding_id:" << c.encoding_id()<< ", get_notifs:" << c.get_notifs()<< std::endl;}catch (const std::exception& e) {std::cerr << "Error:connect database: " << e.what() << std::endl;outfile << "Error:connect database: " << e.what() << std::endl;return -1;}return 0;
}

      (3).删除数据库:

int drop_database(const std::string& dbname)
{try {pqxx::connection c{ options + "postgres" };c.set_client_encoding("GBK");pqxx::nontransaction tx{ c };const std::string str{ "DROP DATABASE " };tx.exec(str + dbname);}catch (const std::exception& e) {std::cerr << "Error:drop database: " << e.what() << std::endl;outfile << "Error:drop database: " << e.what() << std::endl;return -1;}return 0;
}

      (4).创建表:

int create_table(const std::string& dbname, const std::string& command)
{try {pqxx::connection c{ options + dbname };c.set_client_encoding("GBK");pqxx::work w(c);w.exec(command);w.commit();}catch (const std::exception& e) {std::cerr << "Error:create table: " << e.what() << std::endl;outfile << "Error:create table: " << e.what() << std::endl;return -1;}return 0;
}

      (5).删除表:

int drop_table(const std::string& dbname, const std::string& tablename)
{try {pqxx::connection c{ options + dbname };c.set_client_encoding("GBK");pqxx::work w(c);const std::string str{ "DROP TABLE " };w.exec(str + tablename);w.commit();}catch (const std::exception& e) {std::cerr << "Error:drop table: " << e.what() << std::endl;outfile << "Error:drop table: " << e.what() << std::endl;return -1;}return 0;
}

      (6).向表中插入数据:

int insert_into_teacher(const std::string& dbname, int id, const std::string& name, const std::string& addr, const std::string& sex)
{try {pqxx::connection c{ options + dbname + " options='-c client_encoding=GBK'" }; // 有中文时需设置client_encoding=GBK,否则数据库中会显示乱码,推荐使用:c.set_client_encoding("GBK")pqxx::work w(c);const std::string query{ "INSERT INTO teacher (id, name, addr, sex) VALUES ($1, $2, $3, $4)" };w.exec_params(query, id, name, addr, sex);w.commit();}catch (const std::exception& e) {std::cerr << "Error:insert into: " << e.what() << std::endl;outfile << "Error:insert into: " << e.what() << std::endl;return -1;}return 0;
}std::string get_current_time()
{auto timenow = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());std::tm* now_tm = std::localtime(&timenow);std::ostringstream oss;oss << std::put_time(now_tm, "%Y-%m-%d %H:%M:%S");return oss.str();
}int insert_into_student(const std::string& dbname, int id, const std::string& name, const std::string& addr, int age,float score, const std::string& date, const std::string& sex)
{try {pqxx::connection c{ options + dbname };c.set_client_encoding("GBK"); // 有中文时需设置client_encoding=GBK,否则数据库中会显示乱码pqxx::work w(c);const std::string query{ "INSERT INTO student (id, name, addr, age, score, date, sex) VALUES ($1, $2, $3, $4, $5, $6, $7)" };w.exec_params(query, id, name, addr, age, score, date, sex);w.commit();}catch (const std::exception& e) {std::cerr << "Error:insert into: " << e.what() << std::endl;outfile << "Error:insert into: " << e.what() << std::endl;return -1;}return 0;
}

      (7).向已有表中添加、删除列:

int alter_table(const std::string& dbname)
{try {pqxx::connection c{ options + dbname };c.set_client_encoding("GBK");pqxx::work w(c);const std::string query{ "ALTER TABLE teacher " };w.exec(query + "ADD COLUMN hobbies CHAR(64) DEFAULT '游泳'");w.exec(query + "DROP COLUMN addr");w.commit();}catch (const std::exception& e) {std::cerr << "Error:alter table: " << e.what() << std::endl;outfile << "Error:alter table: " << e.what() << std::endl;return -1;}return 0;
}

      (8).删除表中数据:

int delete_table_data(const std::string& dbname)
{try {pqxx::connection c{ options + dbname };c.set_client_encoding("GBK");pqxx::work w(c);const std::string query{ "DELETE FROM teacher WHERE id > 10000 OR sex='女'" };w.exec(query);w.commit();}catch (const std::exception& e) {std::cerr << "Error:delete: " << e.what() << std::endl;outfile << "Error:delete: " << e.what() << std::endl;return -1;}return 0;
}

      (9).调整表中已有数据:

int update_table_data(const std::string& dbname)
{try {pqxx::connection c{ options + dbname };c.set_client_encoding("GBK");pqxx::work w(c);const std::string query{ "UPDATE teacher SET " };w.exec(query + "sex='男' WHERE sex='man'");w.exec(query + "sex='女' WHERE sex='woman'");w.commit();}catch (const std::exception& e) {std::cerr << "Error:update: " << e.what() << std::endl;outfile << "Error:update: " << e.what() << std::endl;return -1;}return 0;
}

      (10).查询表中数据:

int select_table_data(const std::string& dbname)
{try {pqxx::connection c{ options + dbname };c.set_client_encoding("GBK");pqxx::work w(c);const std::string query{ "SELECT * FROM student WHERE age >= 20 AND date > '2024-10-25 16:43:06'" };pqxx::result r(w.exec(query));w.commit();std::cout << "empty:" << r.empty() << ", size:" << r.size() << ", columns:" << r.columns() << std::endl;std::cout << "column name: ";for (auto i = 0; i < r.columns(); ++i)std::cout << r.column_name(i) << "," << r.column_type(r.column_name(i)) << ";";std::cout << std::endl;for (const auto& row : r) {for (const auto& field : row) {std::cout << field.c_str() << "\t";}std::cout << std::endl;}}catch (const std::exception& e) {std::cerr << "Error:select: " << e.what() << std::endl;outfile << "Error:select: " << e.what() << std::endl;return -1;}return 0;
}

      全局变量设置如下:

const std::string options{ "hostaddr=127.0.0.1 port=5432 user=postgres password=spring dbname=" };
const std::string table_teacher{ "CREATE TABLE teacher (""id INTEGER PRIMARY KEY NOT NULL CHECK(id>1000),""name CHAR(32) NOT NULL,""addr CHAR(64) DEFAULT 'BeiJing',""sex CHAR(8) NOT NULL)" };
const std::string table_student{ "CREATE TABLE student (""id INTEGER PRIMARY KEY NOT NULL,""name CHAR(32) NOT NULL,""addr CHAR(64) DEFAULT 'TianJin',""age INTEGER,""score REAL,""date TIMESTAMP,""sex CHAR(8) NOT NULL)" };
std::ofstream outfile;

      主函数如下:

int test_libpqxx()
{
#ifdef _MSC_VERoutfile.open("../../../testdata/output.txt", std::ios::app);
#elseoutfile.open(../../testdata/output.txt", std::ios::app);
#endifif (!outfile.is_open()) {std::cerr << "Error:fail to open file to write\n";return -1;}// databasecreate_database("Info"); // 创建数据库时,数据库中显示的名字为info,而不是Infoconnect_database("info"); // 连接数据库时指定的数据名区分大小写//drop_database("info");// tablecreate_table("info", table_teacher);create_table("info", table_student);insert_into_teacher("info", 1111, "Tom", "HeBei", "man");insert_into_teacher("info", 5555, "Tom", "北京", "男");insert_into_teacher("info", 2222, "小张", "天津", "woman");insert_into_teacher("info", 16625, "xx", "xx", "女");insert_into_student("info", 8, "小王", "HeBei", 32, 88.8, get_current_time(), "男");std::this_thread::sleep_for(std::chrono::seconds(2));insert_into_student("info", 28, "小何", "深圳", 8, 22.22, get_current_time(), "女");insert_into_student("info", 29, "Lucy", "北京", 18, 22.22, get_current_time(), "woman");insert_into_student("info", 33, "Tom", "深圳", 28, 22.22, get_current_time(), "woman");insert_into_student("info", 18, "小李", "上海", 28, 66.6, get_current_time(), "女");std::this_thread::sleep_for(std::chrono::seconds(2));insert_into_student("info", 48, "Tom", "深圳", 38, 22.22, get_current_time(), "woman");alter_table("info");delete_table_data("info");update_table_data("info");select_table_data("info");drop_table("info", "teacher");outfile.close();std::cout << "test finish\n";return 0;
}

     

      (1).创建数据库时,数据库中显示的名字为小写;连接数据库时指定的数据名区分大小写。

      (2).有中文时需设置client_encoding为GBK。

      (3).Debug模式下,使用的也是PostgreSQL中的release库。

      数据库中student表内容如下:

      执行结果如下:

      GitHub:https://github.com/fengbingchun/Messy_Test

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/57915.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C++研发笔记8——C语言程序设计初阶学习笔记6

在第一部分——课前准备的学习中&#xff0c;我就提到了学习C语言的过程中&#xff0c;练习是必不可少的环节&#xff0c;所以本篇笔记我们来进行记录我们学习《C语言程序设计初阶》阶段的第一篇练习文章。 题目一 下面哪个不是C语言内置的数据类型&#xff1a; A.char B.d…

mysql5.7.44 arm 源码编译安装

一、&#xff1a;下载源码&#xff1a;mysql官网&#xff1a;MySQL :: MySQL Downloads #####下载mysql安装包 &#xff1a; 网址&#xff1a;https://www.mysql.com/ 可在页面下载后上传或直接下载。 官网地址首页&#xff0c;拉到最底部&#xff0c;找到社区版本下载&#xf…

财务域——财务信息化

摘要 博文探讨了企业财务信息化相关内容。首先阐述了企业以创造价值为目标&#xff0c;涉及业务、管理和信息三大循环。业务循环涵盖获取 / 支付、转换、销售 / 收款等环节&#xff1b;管理循环包含计划、执行、控制与决策&#xff1b;信息循环强调数据的收集、处理、存储与输…

【Linux | IO多路复用】epoll的底层原理详解

epoll 是一种高效的 I/O 多路复用机制&#xff0c;广泛用于 Linux 系统中&#xff0c;用于处理大量并发的文件描述符。它比传统的 select 和 poll 方法具有更好的性能&#xff0c;特别是在处理大量并发连接时。 1.epoll的设计思路 epoll是在select 出现 N 多年后才被发明的&a…

week08 zookeeper多种安装与pandas数据变换操作-new

课程1-hadoop-Zookeeper安装 Ububtu18.04安装Zookeeper3.7.1 环境与版本 这里采用的ubuntu18.04环境的基本配置为&#xff1a; hostname 为master 用户名为hadoop 静态IP为 192.168.100.3 网关为 192.168.100.2 防火墙已经关闭 /etc/hosts已经配置全版本下载地址&#xff1…

uniapp开发Web页面之动态菜单配置攻略

在uniapp开发过程中&#xff0c;为Web页面配置动态菜单是一个常见的需求。本文将详细介绍如何在uniapp项目中实现动态菜单的配置&#xff0c;帮助开发者轻松应对此类场景。 一、准备工作 确保已安装uniapp开发环境&#xff0c;包括HBuilderX、Node.js等。创建一个uniapp项目&…

软考(网工)——网络安全

文章目录 &#x1f550;网络安全基础1️⃣网络安全威胁类型2️⃣网络攻击类型 &#x1f551;现代加密技术1️⃣私钥密码/对称密码体制2️⃣对称加密算法总结3️⃣公钥密码/非对称密码4️⃣混合密码5️⃣国产加密算法 - SM 系列6️⃣认证7️⃣基于公钥的认证 &#x1f552;Hash …

等保测评:安全计算环境的详细讲解

安全计算环境是信息安全领域中的一个重要概念&#xff0c;旨在确保在计算过程中数据的机密性、完整性和可用性。随着信息技术的迅猛发展和网络攻击的日益频繁&#xff0c;构建安全计算环境显得尤为重要。本文将详细探讨安全计算环境的主要组成部分、特性及其在信息安全中的作用…

MYSQL全局锁、标级锁、行级锁

一、全局锁 全局锁就是对整个数据库实例加锁。 MySQL 提供了一个加全局读锁的方法&#xff0c;命令是 Flush tables with read lock (FTWRL)。当你需要让整个库处于只读状态的时候&#xff0c;可以使用这个命令&#xff0c;之后其他线程的以下语句会被阻塞&#xff1a;数据更新…

好/坏代码实例解读:图文并茂说明

我曾经在某处读到过一句话&#xff0c;基本上有以下内容&#xff1a; “现代世界许多人的生活都依赖于软件&#xff0c;例如控制大型商用客机飞行系统的软件&#xff0c;但软件开发领域大多不受监管。任何人都可以成为自学成才的软件开发人员&#xff0c;并且没有像其他高风险…

python爬虫——Selenium的基本使用

目录 一、Selenium的介绍 二、环境准备 1.安装Selenium 2.安装WebDriver 三、元素定位 1.常用定位元素的方法 2. 通过指定方式定位元素 四、窗口操作 1.最大化浏览器窗口 2.设置浏览器窗口大小 3.切换窗口或标签页 切换回主窗口 4. 关闭窗口 关闭当前窗口 关闭所…

Mybatis mapper文件 resultType和resultMap的区别

在 MyBatis 中&#xff0c;resultType 和 resultMap 都用于定义从数据库查询结果到 Java 对象的映射规则&#xff0c;但它们之间存在着一些关键的区别。以下是对这两者的详细说明和区别&#xff1a; 1. resultType 定义 resultType 是 MyBatis 查询语句中的一个属性&#xf…

Mkdm的51单片机学习日记:实时时钟DS1302

15.2 SPI时序初步认识 单片机常用的通信协议有三种&#xff1a;SPI&#xff0c;UART&#xff0c;I2C SPI&#xff1a;Serial Peripheral Interface 串行外围设备接口&#xff0c;是一种全双工&#xff0c;同步的通信总线 常用于单片机与EEPROM&#xff0c;FLASH&#xff0c;…

Linux中vim的三种主要模式和具体用法

Vim编辑器的三种主要模式 Vim编辑器具有三种主要模式&#xff0c;它们是&#xff1a; 1.命令模式&#xff08;Normal mode&#xff09;&#xff1a;这是Vim的默认模式&#xff0c;用于执行编辑命令、移动光标、删除文本、复制粘贴等操作。在这个模式下&#xff0c;按下键盘上的…

如何使用JMeter进行性能测试的保姆级教程

性能测试是确保网站在用户访问高峰时保持稳定和快速响应的关键环节。作为初学者&#xff0c;选择合适的工具尤为重要。JMeter 是一个强大的开源性能测试工具&#xff0c;可以帮助我们轻松模拟多用户场景&#xff0c;测试网站的稳定性与性能。本教程将引导你通过一个简单的登录场…

w~自动驾驶合集6

我自己的原文哦~ https://blog.51cto.com/whaosoft/12286744 #自动驾驶的技术发展路线 端到端自动驾驶 Recent Advancements in End-to-End Autonomous Driving using Deep Learning: A SurveyEnd-to-end Autonomous Driving: Challenges and Frontiers 在线高精地图 HDMa…

数据结构 - 散列表,初探

今天我们继续学习新的数据结构-散列表。 01定义 我们先来了解一些常见概念名词解释。 散列&#xff1a;散列表的实现叫做散列&#xff0c;是一种实现以常数级时间复杂度执行查找、插入和删除的技术&#xff1b; 散列值&#xff1a;通过散列函数对输入值&#xff08;key&…

对角双差速轮AGV的运动学正解和逆解

对角双差速轮AGV是一种特殊的移动机器人结构,其中两个驱动轮位于车辆的对角线上,通常是前左(FL)和后右(RR)轮,另外两个轮子则是从动轮(万向轮或滑轮),如前右(FR)和后左(RL)轮。这种配置可以在某些特殊应用场景下使用,如需要特定的运动性能或结构设计限制。理解这…

Redis 淘汰策略 问题

前言 相关系列 《Redis & 目录》&#xff08;持续更新&#xff09;《Redis & 淘汰策略 & 源码》&#xff08;学习过程/多有漏误/仅作参考/不再更新&#xff09;《Redis & 淘汰策略 & 总结》&#xff08;学习总结/最新最准/持续更新&#xff09;《Redis &a…

前端零基础入门到上班:【Day2】开发环境VSCode安装

VSCode 安装教程&#xff1a;图文保姆教程 引言 在前端开发中&#xff0c;选择合适的代码编辑器是提高工作效率的重要一步。Visual Studio Code&#xff08;简称 VSCode&#xff09;作为一款强大的开源编辑器&#xff0c;因其简洁易用、功能强大、扩展性好而广受开发者喜爱。…