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…

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

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

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. 关闭窗口 关闭当前窗口 关闭所…

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

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

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

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

Python 协程详解----高性能爬虫

目录 1.基本概念 asyncio和async的关系 asyncio async & await关键字 协程基本语法 多任务协程返回值 案例1 协程在爬虫中的使用 aiohttp模块基本使用 协程案例-扒光一部小说需要多久? 操作数据库 异步redis 异步MySQL 案例2&#xff1a; 知识星球 | 深度连接…

Java篇图书管理系统

目录 前言 一. 图书管理系统的核心 二. 图书管理系统基本框架 2.1 book包 2.1.1 Book&#xff08;书籍类&#xff09; 2.1.2 Booklist (书架类&#xff09; 2.2 user包 2.2.1 User类 2.2.2 Administrator(管理员类) 2.2.3 Visitor&#xff08;用户类&#xff09; 2.…

基于Python大数据的王者荣耀战队数据分析及可视化系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码、微信小程序源码 精品专栏&#xff1a;…

Mybatis-03.入门-配置SQL提示

一.配置SQL提示 目前的Springboot框架在mybatis程序中编写sql语句并没有给到任何的提示信息&#xff0c;这对于开发者而言是很不友好的。因此我们需要配置SQL提示。 配置SQL提示 这样再去写SQL语句就会有提示了。 但是会发现指定表名时并没有给出提示。这是因为&#xff1a…

【综述整理】2015年至2022年图像美学质量评估数据集【附下载链接】

文章目录 2012年-美学数据集AVA-25万-MOS1~10数据集介绍 2015年-移动设备拍摄CLIVE-1K-MOS1~5数据集介绍 2016年-美学数据集AADB-10K-MOS1~10综述摘要 2017年-美学数据集FLICKR-AES-MOS1~5数据集介绍 2018年-户外自然场景KonIQ-10K-MOS1~5数据集介绍标签MOS&#xff0c;1-5分 2…

信息安全工程师(72)网络安全风险评估概述

前言 网络安全风险评估是一项重要的技术任务&#xff0c;它涉及对网络系统、信息系统和网络基础设施的全面评估&#xff0c;以确定存在的安全风险和威胁&#xff0c;并量化其潜在影响以及可能的发生频率。 一、定义与目的 网络安全风险评估是指对网络系统中存在的潜在威胁和风险…