MySQL数据库专栏(五)连接MySQL数据库C API篇

 摘要


        本篇文章主要介绍通过C语言API接口链接MySQL数据库,各接口功能及使用方式,辅助类的封装及调用实例,可以直接移植到项目里面使用。


目录


1、环境配置

1.1、添加头文件

1.2、添加库目录

2、接口介绍

2.1、MySql初始化及数据清理

2.1.1、mysql_ibrary_init 接囗说明

2.1.2、mysql_library_end 接囗说明

2.1.3、mysql_init 接口说明

2.1.4、mysql_close 接口说明

2.2、MySql 数据库链接

2.2.1、mysql_real_connect 接囗说明

2.2.2、mysql_options接口说明

2.3、数据库查询

2.3.1、mysql_real_query接囗说明

2.3.2、mysql_affected_rows接囗说明

2.3.3、mysql_error接囗说明

2.3.4、mysql_use_result接囗说明

2.3.5、mysql_store_result 接囗说明

2.3.6、mysql_fetch_field 接囗说明

2.3.7、mysql_num_felds 接囗说明

2.3.8、mysql_fetch_row接囗说明

2.3.9、mysql_fetch_lengths 接囗说明

2.3.10、mysql_fetch_field_direct 接囗说明

2.3.11、mysql_free_result 接囗说明

2.4、使用实例

3、全网最全辅助类实现

3.1、MySqlHelper.h

3.2、MysqlHelper.cpp

3.3、调用实例


1、环境配置

1.1、添加头文件

打开项目属性页面,在C/C++->常规->附加包含目录中添加“D:\MySQL\mysql-8.0.37-winx64\include”目录。

1.2、添加库目录

 打开项目属性页面,在连接器>常规->附加库目录中添加“D:\MySQL\mysql-8.0.37-winx64\lib”目录。

打开项目属性页面,在连接器>输入->附加依赖项添加“libmysql.lib”目录。

将libmysql.dll文件拷贝到项目的bin目录下。

2、接口介绍

2.1、MySql初始化及数据清理

2.1.1、mysql_library_init接口说明

mysql_library_init 用于初始化整个 MySQL 客户端库。这包括全局变量、内存分配器以及其他与库相关的初始化操作。这个函数通常在程序的开始调用一次,并且应该在任何 MySQL 客户端库函数(如 mysql_init)被调用之前调用。使用方式为mysql_library_init(0, 0, 0);

函数原型

int mysql_library_init(int argc, char **argv, char **groups);

参数说明

argc:命令行参数的数量。

argv:指向命令行参数的指针数组。

groups:一个指向以空字符分隔的组名列表的指针,这些组名指定了要读取的配置文件的部分。如果为 NULL,则读取默认组(通常是 client)。

返回值

如果初始化成功,返回 0。

如果初始化失败,返回非零值。

2.1.2、mysql_library_end接口说明

mysql_library_end和mysql_library_init配套使用,一般在程序退出时调用。

2.1.3、mysql_init接口说明

mysql_init 用于初始化一个 MYSQL 连接句柄。这个句柄将用于后续的数据库连接和查询操作。每次需要与数据库建立连接时,都需要调用这个函数来创建一个新的 MYSQL 连接句柄。

函数原型

MYSQL* mysql_init(MYSQL* mysql)

参数说明

mysql:这是一个指向 MYSQL 结构体的指针。如果传入的是 NULL 指针,则 mysql_init 会自动分配一个新的 MYSQL 结构体并返回其指针;如果传入的是一个已存在的 MYSQL 结构体指针,则该函数会初始化该结构体。

返回值

成功时,返回一个指向已初始化 MYSQL 结构体的指针。

失败时,返回 NULL。通常,当系统内存不足时,mysql_init 会返回 NULL。

2.1.4、mysql_close接口说明

mysql_close和mysql_init配套使用,用于关闭先前通过 mysql_init 初始化的 MYSQL 连接句柄,并释放与该连接相关的所有资源。这个函数在数据库操作完成后调用,以确保连接被正确关闭,并且不会留下任何悬挂的资源或连接。

使用实例

int main()
{mysql_library_init(0, 0, 0);MYSQL* mysql = mysql_init(0);mysql_close(mysql);mysql_library_end();
}

2.2、MySql数据库链接

2.2.1、mysql_real_connect接口说明

mysql_real_connect 是MySQL C API中用于连接到MySQL数据库服务器的一个函数。它提供了一个比 mysql_connect 更加灵活和详细的接口,允许你指定更多的连接参数。

函数原型

MYSQL *mysql_real_connect(MYSQL *mysql, const char *host, const char *user, const char *passwd, const char *db, unsigned int port, const char *unix_socket, unsigned long client_flag);

参数说明

MYSQL *mysql:这是一个已经初始化的MYSQL结构体指针,用于存储连接和查询结果。通常通过mysql_init()函数初始化。

const char *host:MySQL服务器的主机名或IP地址。如果为NULL或字符串"localhost",则连接被视为与本地主机的连接。

const char *user:连接MySQL服务器的用户名。如果为NULL或空字符串"",用户将被视为当前用户。在UNIX环境下,它是当前的登录名;在Windows ODBC下,必须明确指定当前用户名。

const char *passwd:连接MySQL服务器的密码。如果为NULL,仅会对该用户的(拥有1个空密码字段的)用户表中的条目进行匹配检查。密码加密将由客户端API自动处理。

const char *db:连接MySQL服务器后要使用的数据库名。如果为NULL,连接会将默认的数据库设为该值。

unsigned int port:MySQL服务器连接端口,默认为3306。如果指定了非0值,则使用该值作为TCP/IP连接的端口号。

const char *unix_socket:UNIX域套接字文件路径。如果不是NULL,该字符串描述了应使用的套接字或命名管道。

unsigned long client_flag:用于设置连接选项。通常设置为0,但也可以设置为特定标志的组合以允许特定功能。

返回值

如果连接成功,mysql_real_connect返回一个指向MYSQL结构体的指针,该指针代表与MySQL服务器的连接。

如果连接失败,返回NULL。

2.2.2、mysql_options接口说明

mysql_options是一个用于设置额外的连接选项并影响连接行为的函数,经常用于设置链接超时、自动重连。

函数原型

int mysql_options(MYSQL *mysql, enum mysql_option option, const char *arg);

参数说明

MYSQL *mysql:这是一个指向已经初始化的 MYSQL 结构体的指针。

enum mysql_option option:这是一个枚举类型,指定了要设置的选项。MySQL C API 定义了许多这样的选项,例如 MYSQL_OPT_CONNECT_TIMEOUT、MYSQL_OPT_READ_TIMEOUT、MYSQL_OPT_WRITE_TIMEOUT、MYSQL_OPT_COMPRESS、MYSQL_OPT_LOCAL_INFILE 等。

const char *arg(或对于 mysql_options4 的可变参数):这是与所选选项相关联的参数。它的类型和含义取决于 option 参数的值。例如,对于 MYSQL_OPT_CONNECT_TIMEOUT,参数应该是一个指向表示秒数的整数的指针(但通常通过类型转换传递为 const char *,因为实际实现可能接受 void * 并进行内部转换)。

返回值

如果成功,mysql_options 返回 0。

如果失败(例如,因为传递了无效的选项或参数),它返回非零值。

使用实例

	mysql_library_init(0, 0, 0);MYSQL* mysql = mysql_init(0);const char* host = "127.0.0.1";    const char* user = "root";const char* pass = "luoboshou123";const char* db = "db_demo";		//数据库名称//设定超时3秒int to = 3;int re = mysql_options(mysql, MYSQL_OPT_CONNECT_TIMEOUT, &to);if (re != 0){cout << "mysql_options failed!" << mysql_error(mysql) << endl;}//自动重连int recon = 1;re = mysql_options(mysql, MYSQL_OPT_RECONNECT, &recon);if (re != 0){cout << "mysql_options failed!" << mysql_error(mysql) << endl;}if (!mysql_real_connect(mysql, host, user, pass, db, 3306, 0, 0)){cout << "mysql connect failed!" << mysql_error(mysql) << endl;}else{cout << "mysql connect success!" << endl;}for (int i = 0; i < 1000; i++){int re = mysql_ping(mysql);if (re == 0){cout << host << ":mysql ping success!" << endl;}else{cout << host << ":mysql ping failed! " << mysql_error(mysql) << endl;}this_thread::sleep_for(1s);}mysql_close(mysql);mysql_library_end();

2.3、数据库查询

2.3.1、mysql_real_query接口说明

mysql_real_query 是 MySQL C API 中的一个函数,用于向 MySQL 数据库服务器发送一个 SQL 查询。

函数原型

int mysql_real_query(MYSQL *mysql, const char *query, unsigned long length)

参数说明

mysql:这是一个指向已经通过 mysql_init 初始化并通过 mysql_real_connect 成功连接到数据库的 MYSQL 连接对象的指针。

query:这是一个指向包含要执行的 SQL 语句的字符串的指针。

length:这是 query 字符串的长度(以字节为单位)。如果你传递的是以空字符('\0')结尾的 C 字符串,你可以使用 strlen(query) 来获取这个长度。但是,如果你处理的是二进制数据或者不想依赖空字符来终止字符串,你应该明确指定长度。

返回值

如果查询成功执行,mysql_real_query 返回 0。

2.3.2、mysql_affected_rows接口说明

mysql_affected_rows 函数返回上一个执行成功的 INSERT、UPDATE 或 DELETE 语句所影响的行数。这对于需要统计或验证操作结果的场景非常有用

函数原型

my_ulonglong mysql_affected_rows(MYSQL *mysql)

参数说明

mysql:这是一个指向已经通过 mysql_init 初始化并通过 mysql_real_connect 成功连接到数据库的 MYSQL 连接对象的指针。

返回值

返回一个 my_ulonglong 类型的值,表示最近一次执行 INSERT、UPDATE 或 DELETE 语句所影响的行数。

2.3.3、mysql_error接口说明

mysql_error 是 MySQL C API 中的一个函数,用于获取最近一次 MySQL 函数调用产生的错误消息。当你调用 MySQL 的某个函数(如 mysql_query, mysql_store_result, mysql_real_query 等)并且该函数返回错误时,你可以使用 mysql_error 来获取关于该错误的详细信息。

函数原型

const char *mysql_error(MYSQL *mysql)

参数说明

mysql:这是一个指向已经通过 mysql_init 初始化并通过 mysql_real_connect(或 mysql_connect,尽管这是较旧的函数)成功连接到数据库的 MYSQL 连接对象的指针。

返回值

返回一个指向描述最近一次错误的字符串的指针。如果最近一次 MySQL 函数调用成功,没有产生错误,返回的字符串可能是一个空字符串("")或者表示没有错误的消息(这取决于 MySQL 的版本和配置)。

2.3.4、mysql_use_result接口说明

mysql_use_result 是 MySQL C API 中的一个函数,用于逐行获取查询结果集。这个函数与 mysql_store_result 相对应,但它们在处理大型结果集时的工作方式有所不同。

函数原型

MYSQL_RES *mysql_use_result(MYSQL *mysql)

参数说明

mysql:这是一个指向已经通过 mysql_init 初始化并通过 mysql_real_connect 成功连接到数据库的 MYSQL 连接对象的指针。

返回值

如果成功,返回一个指向 MYSQL_RES 结果集的指针,你可以使用这个结果集来逐行获取查询结果。

如果失败,返回 NULL。此时,你可以通过调用 mysql_error(mysql) 来获取错误消息。

2.3.5、mysql_store_result接口说明

mysql_store_result 是 MySQL C API 中的一个函数,用于从服务器检索查询的全部结果集并将其存储在客户端。

函数原型

MYSQL_RES *mysql_store_result(MYSQL *mysql)

参数说明

mysql:这是一个指向已经通过 mysql_init 初始化并通过 mysql_real_connect 成功连接到数据库的 MYSQL 连接对象的指针

返回值

如果成功,返回一个指向 MYSQL_RES 结构体的指针,该结构体包含了查询结果集的所有信息。你可以使用 mysql_fetch_row、mysql_num_rows、mysql_num_fields 等函数来访问和处理这个结果集。

如果失败(例如,由于内存不足或查询失败),返回 NULL。此时,你可以通过调用 mysql_error(mysql) 来获取错误消息。

2.3.6、mysql_fetch_field接口说明

mysql_fetch_field 是 MySQL C API 中的一个函数,用于从结果集中获取当前字段的信息。

函数原型

MYSQL_FIELD *mysql_fetch_field(MYSQL_RES *result)

参数说明

result:这是通过 mysql_store_result 或 mysql_use_result 函数执行查询后获得的结果集。

返回值

成功时,mysql_fetch_field 返回一个指向 MYSQL_FIELD 结构体的指针,该结构体包含了当前字段的信息。

如果所有字段信息都已被检索完毕,或者发生错误(例如,结果集为空),则返回 NULL。

MYSQL_FIELD 结构体

MYSQL_FIELD 结构体通常包含以下字段(具体字段可能因 MySQL 版本而异):

name:字段的名称。

org_name:字段的原始名称(如果适用)。

table:字段所属的表的名称(如果适用)。

org_table:字段所属的原始表的名称(如果适用)。

db:字段所属的数据库的名称(如果适用)。

catalog:字段所属的目录的名称(如果适用,通常为空)。

def:字段的默认值(如果适用)。

length:字段的长度。

max_length:字段的最大可能长度。

name_length:字段名称的长度。

org_name_length:字段原始名称的长度(如果适用)。

table_length:字段所属表的名称的长度(如果适用)。

org_table_length:字段所属原始表的名称的长度(如果适用)。

db_length:字段所属数据库的名称的长度(如果适用)。

catalog_length:字段所属目录的名称的长度(如果适用)。

def_length:字段默认值的长度(如果适用)。

flags:字段的标志,这些标志可以是多个值的组合,用于描述字段的特性(例如,是否允许 NULL 值,是否是主键等)。

type:字段的类型(例如,MYSQL_TYPE_INT、MYSQL_TYPE_VARCHAR 等)。

decimals:字段的小数位数(对于数值类型字段)。

2.3.7、mysql_num_fields接口说明

mysql_num_fields 是 MySQL C API 中的一个函数,用于获取查询结果集中的字段数量。

函数原型

unsigned int mysql_num_fields(MYSQL_RES *result)

参数说明

result:这是通过 mysql_store_result 或 mysql_use_result 函数执行查询后获得的结果集。

返回值

mysql_num_fields 返回一个无符号整数,表示结果集中字段的数量。如果结果集为空或发生错误,返回值可能是 0,但更常见的做法是通过检查 mysql_store_result 或 mysql_use_result 的返回值来确认查询是否成功执行。

2.3.8、mysql_fetch_row接口说明

mysql_fetch_row 是 MySQL C API 中的一个函数,用于从结果集中获取下一行的数据。

函数原型

MYSQL_ROW mysql_fetch_row(MYSQL_RES *result);

参数说明

result:这是通过 mysql_store_result 或 mysql_use_result 函数执行查询后获得的结果集。

返回值

mysql_fetch_row 返回一个 MYSQL_ROW 类型的值,这是一个指向字符串数组的指针,数组中的每个字符串代表结果集中当前行的一个字段(列)的值。如果所有行都已检索完毕,或者发生错误(例如,结果集为空),则返回 NULL。

MYSQL_ROW 实际上是一个 char** 类型的别名,它指向一个以空指针结尾的字符串数组。因此,你可以像处理普通的 C 字符串数组一样处理 MYSQL_ROW。

2.3.9、mysql_fetch_lengths接口说明

mysql_fetch_lengths 是 MySQL C API 中的一个函数,用于获取当前行中各字段值的长度。

函数原型

unsigned long *mysql_fetch_lengths(MYSQL_RES *result)

参数说明

result:这是通过 mysql_store_result 或 mysql_use_result 函数执行查询后获得的结果集。

返回值

mysql_fetch_lengths 返回一个指向无符号长整数数组的指针,数组中的每个元素代表结果集中当前行对应字段的长度(不包括任何终结 NULL 字符)。如果发生错误,或者当前行已经超出了结果集的范围(比如在调用 mysql_fetch_row 之前或在检索了结果集中的所有行之后调用 mysql_fetch_lengths),则返回 NULL。

2.3.10、mysql_fetch_field_direct接口说明

mysql_fetch_field_direct 是 MySQL C API 中的一个函数,用于从结果集中获取指定列的字段信息。

函数原型

MYSQL_FIELD *mysql_fetch_field_direct(MYSQL_RES *result, unsigned int fieldnr)

参数说明

result:这是一个指向 MYSQL_RES 结构体的指针,该结构体包含了查询结果集的信息。这个结构体通常是通过调用 mysql_store_result 或 mysql_use_result 函数获得的。

fieldnr:这是要获取的字段的索引(从 0 开始)。索引值应该小于结果集中字段的总数,该总数可以通过调用 mysql_num_fields 函数获得。

返回值

mysql_fetch_field_direct 返回一个指向 MYSQL_FIELD 结构体的指针,该结构体包含了指定索引位置的字段的元数据。如果指定的索引超出了结果集中字段的范围,或者发生了其他错误,函数将返回 NULL。

2.3.11、mysql_free_result接口说明

mysql_free_result 是 MySQL C API 中的一个函数,用于释放由 mysql_store_result 或 mysql_use_result 函数分配的内存,这些内存用于存储从数据库查询返回的结果集。当你不再需要访问查询结果时,应该调用 mysql_free_result 来释放这些资源,以避免内存泄漏。

函数原型

void mysql_free_result(MYSQL_RES *result)

参数说明

result:这是一个指向 MYSQL_RES 结构体的指针,该结构体包含了查询结果集的信息。这个结构体通常是通过调用 mysql_store_result 或 mysql_use_result 函数获得的。

返回值

mysql_free_result 函数没有返回值。它直接操作传入的 MYSQL_RES 结构体指针,释放与该结果集相关的所有资源。在调用此函数之后,传入的 result 指针将不再有效,你不应该再尝试使用它。

2.4、使用实例

#include <iostream>
#include "mysql.h"
#include <thread>
#include <string>
#include <sstream>using namespace std;std::string GBKToUTF8(const char *data)
{string re = "";
#ifdef _WIN32//gbk转为unicode win utf16//1 统计转换后字节数int len = MultiByteToWideChar(CP_ACP,		//转换的格式0,		//默认的转换方式data,		//输入的字节-1,		//输出的字符串大小 -1 找'\0'0,		//输出0		//输出的空间大小);if (len <= 0) return re;wstring udata;udata.resize(len);MultiByteToWideChar(CP_ACP, 0, data, -1, (wchar_t*)udata.data(), len);// 2 unicode 转 utf-8len = WideCharToMultiByte(CP_UTF8, 0, (wchar_t*)udata.data(), -1, 0, 0,0,		//失败默认替代字符0		//是否使用默认替代);if (len <= 0) return re;re.resize(len);WideCharToMultiByte(CP_UTF8, 0, (wchar_t*)udata.data(), -1, (char*)re.data(), len, 0, 0);
#elsere.resize(1024);int inlen = strlen(data);Convert((char*)"gbk", (char*)"utf-8", (char*)data, inlen, (char*)re.data(), re.size());int outlen = strlen(re.data());re.resize(outlen);
#endifreturn re;
}std::string UTF8ToGBK(char *data)
{string re = "";
#ifdef _WIN32//utf8转为unicode win utf16//1 统计转换后字节数int len = MultiByteToWideChar(CP_UTF8,		//转换的格式0,		//默认的转换方式data,		//输入的字节-1,		//输出的字符串大小 -1 找'\0'0,		//输出0		//输出的空间大小);if (len <= 0) return re;wstring udata;udata.resize(len);MultiByteToWideChar(CP_UTF8, 0, data, -1, (wchar_t*)udata.data(), len);// 2 unicode 转 GBKlen = WideCharToMultiByte(CP_ACP, 0, (wchar_t*)udata.data(), -1, 0, 0,0,		//失败默认替代字符0		//是否使用默认替代);if (len <= 0) return re;re.resize(len);WideCharToMultiByte(CP_ACP, 0, (wchar_t*)udata.data(), -1, (char*)re.data(), len, 0, 0);
#elsere.resize(1024);int inlen = strlen(data);Convert((char*)"utf-8", (char*)"gbk", (char*)data, inlen, (char*)re.data(), re.size());int outlen = strlen(re.data());re.resize(outlen);
#endifreturn re;
}int main()
{mysql_library_init(0, 0, 0);MYSQL* mysql = mysql_init(0);const char* host = "127.0.0.1";    const char* user = "root";const char* pass = "luoboshou123";const char* db = "db_demo";		//数据库名称if (!mysql_real_connect(mysql, host, user, pass, db, 3306, 0, 0)){cout << "mysql connect failed!" << mysql_error(mysql) << endl;}else{cout << "mysql connect success!" << endl;}string strSql = "";int res = 0;//创建表strSql = "DROP TABLE IF EXISTS `t_user`";strSql = GBKToUTF8(strSql.c_str());res = mysql_real_query(mysql, strSql.c_str(), strSql.size());if (res != 0){cout << "mysql_query failed!" << mysql_error(mysql) << endl;}strSql = "CREATE TABLE IF NOT EXISTS `t_user` (\`id` INT unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',\`user_name` varchar(128) NOT NULL DEFAULT '' COMMENT '登录名',\`password` varchar(512) NOT NULL DEFAULT '' COMMENT '密码',\`nick_name` varchar(128) NOT NULL DEFAULT '' COMMENT '昵称',\`user_no` varchar(128) NOT NULL DEFAULT '' COMMENT '身份证号',\`status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '0(正常);1(禁用)',\`phone` char(11) NOT NULL DEFAULT '' COMMENT '手机号',\PRIMARY KEY(`id`),\UNIQUE KEY `user_name` (`user_name`),\UNIQUE KEY `phone` (`phone`)\) ENGINE = InnoDB DEFAULT CHARACTER SET = utf8 COLLATE = utf8_bin; ";strSql = GBKToUTF8(strSql.c_str());res = mysql_real_query(mysql, strSql.c_str(), strSql.size());if (res != 0){cout << "mysql_query failed!" << mysql_error(mysql) << endl;}//插入表数据strSql = "insert into t_user (user_name,password,nick_name,user_no,status,phone) values('张三11','12345678','红太阳','131024685941523145',0,'13465231510')";strSql = GBKToUTF8(strSql.c_str());res = mysql_real_query(mysql, strSql.c_str(), strSql.size());if (res == 0){int count = mysql_affected_rows(mysql);cout << "insert mysql_affected_rows " << count << endl;}else{cout << "insert failed!" << mysql_error(mysql) << endl;}for (int i = 0; i < 5; i++) {stringstream ss;ss << "insert into t_user (user_name,password,nick_name,user_no,status,phone) values('张三11";ss << i;ss << "','12345678','红太阳','131024685941523145',0,'1346523151";ss << i + 2;ss << "')";strSql = ss.str();strSql = GBKToUTF8(strSql.c_str());res = mysql_real_query(mysql, strSql.c_str(), strSql.size());if (res == 0){int count = mysql_affected_rows(mysql);cout << "insert mysql_affected_rows " << count << endl;}else{cout << "insert failed!" << mysql_error(mysql) << endl;}}//修改表数据strSql = "update t_user set `nick_name`='红太阳2' where id=1";strSql = GBKToUTF8(strSql.c_str());res = mysql_real_query(mysql, strSql.c_str(), strSql.size());if (res == 0){int count = mysql_affected_rows(mysql);cout << "update mysql_affected_rows " << count << endl;}else{cout << "update failed!" << mysql_error(mysql) << endl;}//删除表数据strSql = "delete from t_user where id=1";strSql = GBKToUTF8(strSql.c_str());res = mysql_real_query(mysql, strSql.c_str(), strSql.size());if (res == 0){int count = mysql_affected_rows(mysql);cout << "delete mysql_affected_rows " << count << endl;}else{cout << "delete failed!" << mysql_error(mysql) << endl;}//查询数据strSql = "select * from t_user";strSql = GBKToUTF8(strSql.c_str());res = mysql_real_query(mysql, strSql.c_str(), strSql.size());if (res != 0) {cout << "mysql_real_query faied! " << strSql << " " << mysql_error(mysql) << endl;}else{cout << "mysql_real_query success! " << strSql << endl;}MYSQL_RES* result = mysql_use_result(mysql);if (!result){cout << "mysql_use_result faied! " << mysql_error(mysql) << endl;}MYSQL_ROW row;int num = mysql_num_fields(result);while (row = mysql_fetch_row(result)){unsigned long* lens = mysql_fetch_lengths(result);for (int i = 0; i < num; i++){cout << mysql_fetch_field_direct(result, i)->name << ":";if (row[i])cout << UTF8ToGBK(row[i]);elsecout << "NULL";cout << ",";}cout  << endl;}mysql_free_result(result);mysql_close(mysql);mysql_library_end();system("pause");
}

3、全网最全辅助类实现

3.1、MySqlHelper.h

#ifndef MYSQLHELPER_H
#define MYSQLHELPER_H#include <mutex>
#include <vector>
#include <map>
#include <string>
#include <mysql.h>struct MYSQL;
struct MYSQL_RES;
namespace db {typedef struct {const char* host;const char* user;const char* pass;const char* db;unsigned short port;unsigned long flag;} MYSQLCCONNECT;typedef std::vector<std::map<std::string, std::string>> DataTable;class MySqlHelper {public:static const MYSQLCCONNECT conn;private://基础方法-------------------------------------//初始化Mysql APIbool Init();//清理占用的所有资源void Close();//数据库连接 flag设置支持多条语句bool Connect(MYSQLCCONNECT conn, std::string& errMsg, int connectTimeout = 5, unsigned long flag = 0);//执行sql语句 if sqllen = 0; strlen获取字符长度bool Query(std::string sql, std::string& errMsg);//Mysql参数的设定 Connect之前调用bool Options(mysql_option opt, std::string& errMsg, const void* arg);//连接超时时间设置bool SetConnectTimeout(int sec, std::string& errMsg);//释放结果集占用的空间void FreeResult();//基础方法-------------------------------------public://常用方法-------------------------------------//执行增删改动作int ExecuteNonSql(const std::string& sql, std::string& errMsg);//执行单一结果的查询bool ExecuteSingleResult(const std::string& sql, std::string& refResult, std::string& errMsg);//结果集查询bool ExecuteResult(const std::string& sql, DataTable& refTable, std::string& errMsg, bool is_use = true);//常用方法-------------------------------------//事务接口-------------------------------------bool StartTransaction(std::string& errMsg);bool Commit(std::string& errMsg);bool RollBack(std::string& errMsg);//基于事务执行增删改动作int ExecuteNonSqlTransaction(const std::string& sql, std::string& errMsg);//基于事务执行单一结果的查询bool ExecuteSingleResultTransaction(const std::string& sql, std::string& refResult, std::string& errMsg);//基于事务进行结果集查询bool ExecuteResultTransaction(const std::string& sql, DataTable& refTable, std::string& errMsg, bool is_use = true);//事务接口-------------------------------------//字符集转换-------------------------------------std::string UTF8ToGBK(std::string& data);std::string GBKToUTF8(std::string& data);//字符集转换-------------------------------------//数据库链接状态bool isConn();private:MYSQL* mysql = 0;MYSQL_RES* result = 0;};
}#endif

 3.2、MySqlHelper.cpp

#include "MySqlHelper.h"
#include <iostream>using namespace std;namespace db {const MYSQLCCONNECT MySqlHelper::conn = { "127.0.0.1","root","luoboshou123","db_demo" };bool MySqlHelper::Init(){Close();this->mysql = mysql_init(0);if (!this->mysql) {return false;}return true;}void MySqlHelper::Close(){FreeResult();if (this->mysql) {mysql_close(this->mysql);this->mysql = NULL;}}bool MySqlHelper::Connect(MYSQLCCONNECT conn, std::string& errMsg, int connectTimeout, unsigned long flag){if (!this->mysql && !Init()) {errMsg = "Mysql connect failed! mysql is not init! ";return false;}if (!SetConnectTimeout(connectTimeout, errMsg)) {return false;}if (!mysql_real_connect(this->mysql, conn.host, conn.user, conn.pass, conn.db, conn.port, 0, flag)) {errMsg = "Mysql connect failed! : " + string(mysql_error(this->mysql));return false;}return true;}bool MySqlHelper::Query(std::string sql, std::string& errMsg){if (!this->mysql) {errMsg = "Query failed: mysql is NULL";return false;}if (sql.empty()) {errMsg = "sql is null";return false;}sql = GBKToUTF8(sql);int re = mysql_real_query(mysql, sql.c_str(), (unsigned long)sql.length());if (re != 0) {errMsg = "mysql_real_query failed! : " + string(mysql_error(this->mysql));return false;}return true;}bool MySqlHelper::Options(mysql_option opt, std::string& errMsg, const void* arg){if (!this->mysql) {errMsg = "Options failed: mysql is NULL";return false;}int re = mysql_options(this->mysql, (mysql_option)opt, arg);if (re != 0) {errMsg = "mysql_options failed!: " + string(mysql_error(this->mysql));return false;}return true;}bool MySqlHelper::SetConnectTimeout(int sec, std::string& errMsg){return Options(MYSQL_OPT_CONNECT_TIMEOUT, errMsg, &sec);}int MySqlHelper::ExecuteNonSql(const std::string& sql, std::string& errMsg){int res = -1;if (!Connect(conn, errMsg)){goto END;}if (sql.empty()){errMsg = "sql is empty";goto END;}if (!Query(sql, errMsg)){goto END;}res = mysql_affected_rows(mysql);END:Close();return res;}bool MySqlHelper::ExecuteSingleResult(const std::string& sql, std::string& refResult, std::string& errMsg){bool res = true;MYSQL_ROW row;int num;if (!Connect(conn, errMsg)){res = false;goto END;}if (sql.empty()){errMsg = "sql is empty";res = false;goto END;}if (!Query(sql, errMsg)){res = false;goto END;}this->result = mysql_store_result(this->mysql);if (!this->result) {errMsg = "mysql_store_result failed!:" + string(mysql_error(this->mysql));res = false;goto END;}row = mysql_fetch_row(this->result);if (!row) {errMsg = "mysql_fetch_row : No data found";res = false;goto END;}//列的数量num = mysql_num_fields(this->result);if (num != 1){errMsg = "mysql_num_fields : fields not 1";res = false;goto END;}refResult = row[0];END:Close();return res;}bool MySqlHelper::ExecuteResult(const std::string& sql, DataTable& refTable, std::string& errMsg, bool is_use){bool res = true;MYSQL_ROW row;int num;if (!Connect(conn, errMsg)){res = false;goto END;}if (sql.empty()){errMsg = "sql is empty";res = false;goto END;}if (!Query(sql, errMsg)){res = false;goto END;}FreeResult();if (is_use) {this->result = mysql_use_result(mysql);}else {this->result = mysql_store_result(mysql);}num = mysql_num_fields(result);while (row = mysql_fetch_row(this->result)){if (!row) {res = false;goto END;}map<string, string> rowData;for (int i = 0; i < num; i++){string key, value;key = mysql_fetch_field_direct(result, i)->name;if (row != NULL) {value = row[i];value = UTF8ToGBK(value);}else {value = "";}rowData[key] = value;}refTable.push_back(rowData);}END:Close();return res;}void MySqlHelper::FreeResult(){if (this->result) {mysql_free_result(this->result);this->result = NULL;}}bool MySqlHelper::StartTransaction(std::string& errMsg){if (!Connect(conn, errMsg)){return false;}if (!Query("START TRANSACTION", errMsg)){return false;}if (!Query("set autocommit=0", errMsg)){return false;}return true;}bool MySqlHelper::Commit(std::string& errMsg){if (!Query("commit", errMsg)){return false;}if (!Query("set autocommit=1", errMsg)){return false;}Close();return true;}bool MySqlHelper::RollBack(std::string& errMsg){if (!Query("rollback", errMsg)){return false;}if (!Query("set autocommit=1", errMsg)){return false;}Close();return true;}int MySqlHelper::ExecuteNonSqlTransaction(const std::string& sql, std::string& errMsg){int res = -1;if (sql.empty()){errMsg = "sql is empty";goto END;}if (!Query(sql, errMsg)){goto END;}res = mysql_affected_rows(mysql);END:return res;}bool MySqlHelper::ExecuteSingleResultTransaction(const std::string& sql, std::string& refResult, std::string& errMsg){bool res = true;MYSQL_ROW row;int num;if (sql.empty()){errMsg = "sql is empty";res = false;goto END;}if (!Query(sql, errMsg)){res = false;goto END;}this->result = mysql_store_result(this->mysql);if (!this->result){errMsg = "mysql_store_result failed!:" + string(mysql_error(this->mysql));res = false;goto END;}row = mysql_fetch_row(this->result);if (!row) {errMsg = "mysql_fetch_row : No data found";res = false;goto END;}num = mysql_num_fields(this->result);if (num != 1){errMsg = "mysql_num_fields : fields not 1";res = false;goto END;}refResult = row[0];END:return res;}bool MySqlHelper::ExecuteResultTransaction(const std::string& sql, DataTable& refTable, std::string& errMsg, bool is_use){bool res = true;MYSQL_ROW row;int num;if (sql.empty()){errMsg = "sql is empty";res = false;goto END;}if (!Query(sql, errMsg)){res = false;goto END;}FreeResult();if (is_use) {this->result = mysql_use_result(mysql);}else {this->result = mysql_store_result(mysql);}num = mysql_num_fields(result);refTable.clear();while (row = mysql_fetch_row(this->result)){if (!row) {res = false;goto END;}map<string, string> rowData;for (int i = 0; i < num; i++){string key, value;key = mysql_fetch_field_direct(result, i)->name;if (row != NULL) {value = row[i];value = UTF8ToGBK(value);}else {value = "";}rowData[key] = value;}refTable.push_back(rowData);}END:return res;}bool MySqlHelper::isConn(){return mysql->net.vio;}std::string MySqlHelper::GBKToUTF8(std::string& data){string re = "";
#ifdef _WIN32//gbk转为unicode win utf16//1 统计转换后字节数int len = MultiByteToWideChar(CP_ACP,		//转换的格式0,		//默认的转换方式data.c_str(),		//输入的字节-1,		//输出的字符串大小 -1 找'\0'0,		//输出0		//输出的空间大小);if (len <= 0) return re;wstring udata;udata.resize(len);MultiByteToWideChar(CP_ACP, 0, data.c_str(), -1, (wchar_t*)udata.data(), len);// 2 unicode 转 utf-8len = WideCharToMultiByte(CP_UTF8, 0, (wchar_t*)udata.data(), -1, 0, 0,0,		//失败默认替代字符0		//是否使用默认替代);if (len <= 0) return re;re.resize(len);WideCharToMultiByte(CP_UTF8, 0, (wchar_t*)udata.data(), -1, (char*)re.data(), len, 0, 0);
#elsere.resize(1024);int inlen = strlen(data);Convert((char*)"gbk", (char*)"utf-8", (char*)data, inlen, (char*)re.data(), re.size());int outlen = strlen(re.data());re.resize(outlen);
#endifreturn re;}std::string MySqlHelper::UTF8ToGBK(std::string& data){string re = "";
#ifdef _WIN32//utf8转为unicode win utf16//1 统计转换后字节数int len = MultiByteToWideChar(CP_UTF8,		//转换的格式0,		//默认的转换方式data.c_str(),		//输入的字节-1,		//输出的字符串大小 -1 找'\0'0,		//输出0		//输出的空间大小);if (len <= 0) return re;wstring udata;udata.resize(len);MultiByteToWideChar(CP_UTF8, 0, data.c_str(), -1, (wchar_t*)udata.data(), len);// 2 unicode 转 GBKlen = WideCharToMultiByte(CP_ACP, 0, (wchar_t*)udata.data(), -1, 0, 0,0,		//失败默认替代字符0		//是否使用默认替代);if (len <= 0) return re;re.resize(len);WideCharToMultiByte(CP_ACP, 0, (wchar_t*)udata.data(), -1, (char*)re.data(), len, 0, 0);
#elsere.resize(1024);int inlen = strlen(data);Convert((char*)"utf-8", (char*)"gbk", (char*)data, inlen, (char*)re.data(), re.size());int outlen = strlen(re.data());re.resize(outlen);
#endifreturn re;}
}

3.3、调用实例

#include <iostream>
#include "mysql.h"
#include <thread>
#include <string>
#include <sstream>
#include "MySqlHelper.h"using namespace std;
using namespace db;int main()
{MySqlHelper helper;string errMsg;bool flag = false;//增删改实例//string sql = "insert into t_user (user_name,password,nick_name,user_no,status,phone) values('张三11','12345678','红太阳','131024685941523145',0,'13465231510')";string sql = "update t_user set nick_name='小王1' where id = 24";//string sql = "delete from t_user where id = 24";int iRes = 0;iRes = helper.ExecuteNonSql(sql, errMsg);if (iRes == -1) {cout << errMsg << endl;}cout << iRes << endl;//单一结果查询实例sql = "select count(*) from t_user";string refResult;flag = helper.ExecuteSingleResult(sql, refResult, errMsg);if (!flag) {cout << errMsg << endl;}cout << refResult << endl;//结果集查询实例DataTable dt;sql = "select * from t_user";flag = helper.ExecuteResult(sql, dt, errMsg);if (!flag) {cout << errMsg << endl;}for (int i = 0; i < dt.size(); i++) {cout << dt[i]["id"] << " ";cout << dt[i]["user_name"] << " ";cout << dt[i]["password"] << " ";cout << dt[i]["nick_name"] << " ";cout << dt[i]["user_no"] << " ";cout << dt[i]["status"] << " ";cout << dt[i]["phone"] << endl;}//事务实例helper.StartTransaction(errMsg);sql = "update t_user set nick_name='小事7' where id=20";helper.ExecuteNonSqlTransaction(sql, errMsg);sql = "update t_user set nick_name='小事8' where id=22";helper.ExecuteNonSqlTransaction(sql, errMsg);sql = "select count(*) from t_user";helper.ExecuteSingleResultTransaction(sql, refResult, errMsg);cout << refResult << endl;//helper.Commit(errMsg);helper.RollBack(errMsg);system("pause");
}

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

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

Ubuntu系统被木马程序攻击,运行莫名进程杀掉又自动重启解决办法

问题&#xff1a;Ubuntu系统被攻击了&#xff0c;有莫名进程运行杀掉又自动重启。 原因&#xff1a;攻击原因估计是用户名和密码过于简单&#xff0c;ssh服务穿透时等被暴力破解了。 nvidia-smi&#xff1a;存在莫名的./java程序&#xff0c;kill掉也会重启其它木马进程&#…

Java基于SpringBoot+Vue框架的宠物寄养系统(V2.0),附源码,文档

博主介绍&#xff1a;✌程序员徐师兄、7年大厂程序员经历。全网粉丝12w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;…

【MySQL】函数

3.函数 MySQL中的函数主要分为以下四类&#xff1a; 字符串函数、数值函数、日期函数、流程函数。 3.1 字符串函数 演示如下&#xff1a; A. concat : 字符串拼接 select concat(Hello , MySQL);B. lower : 全部转小写 select lower(Hello);C. upper : 全部转大写 select…

Android笔记(三十五):用责任链模式封装一个App首页Dialog管理工具

背景 项目需要在首页弹一系列弹窗&#xff0c;每个弹窗是否弹出都有自己的策略&#xff0c;以及哪个优先弹出&#xff0c;哪个在上一个关闭后再弹出&#xff0c;为了更好管理&#xff0c;于是封装了一个Dialog管理工具 效果 整体采用责任链模块设计&#xff0c;控制优先级及弹…

【实战篇P2-5】手把手实现STM32+ESP8266+原子云服务器+手机APP应用——第五节-编写Android手机APP程序实现接入原子云服务器

使用的开发软件是Android studio Android SDK(运行环境 :最低版本 21(Android 5.0) 最高版本 29 (Android 9.0) Gradle 版本 :4.6 根据源码,可自定义修改界面,修改名称,根据需求自定义数据展示界面等,修改app图标及名称等。 目录 Android程序设计 Android…

2024双十一数码好物推荐?双十一超值数码好物汇总别错过!

随着2024年双十一购物狂欢节临近尾声&#xff0c;各大电商平台的促销活动已经进入了最后的冲刺阶段。在这场年度最大的购物盛宴中&#xff0c;数码产品无疑是消费者关注的焦点。无论是提升工作效率的电脑、平板&#xff0c;还是丰富娱乐生活的手机、耳机&#xff0c;各大品牌纷…

Android V 挂起线程超时导致system_server挂掉

问题背景 最近Android v的平台频繁爆monkey异常停止的问题,分析到根因不是频繁dump堆栈导致system_server挂掉就是三方应用进程内部死锁导致anr,然后system_server挂起线程超时,system_server就崩了。 解决方案 先来看看anr导致死锁的场景如何分析 从log来看确认为syste…

评估 机器学习 回归模型 的性能和准确度

回归 是一种常用的预测模型&#xff0c;用于预测一个连续因变量和一个或多个自变量之间的关系。 那么&#xff0c;最后评估 回归模型 的性能和准确度非常重要&#xff0c;可以帮助我们判断模型是否有效并进行改进。 接下来&#xff0c;和大家分享如何评估 回归模型 的性能和准…

图片循环轮播,悬停停止

可直接执行HTML 代码 template 代码在下面 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Swip…

Transformer介绍(一)

Transformer是一种特殊的神经网络&#xff0c;一种机器学习模型。 谷歌在2017年推出的原版Transformer&#xff0c;论文《Attention Is All You Need》&#xff0c;专注于将一种语言的文本翻译成另一种。 而我们要关注的Transformer变种&#xff0c;即构建ChatGPT等工具的模型…

MySQL之索引(1)(索引概念与作用、红黑树、b树、b+树)(面试高频)

目录 一、索引的概念、作用。 &#xff08;1&#xff09;介绍。 &#xff08;2&#xff09;为啥索引能优化sql查询&#xff1f; 1、某张表(emp)结构以及数据如下。 2、假如执行的SQL语句为&#xff1a;select * from emp where empno7844; 3、对比与总结。 &#xff08;3&#…

pytest+request+allure接口自动化框架搭建分享

介绍分享一个接口自动化框架搭建方法 (pytestrequestallure)&#xff0c;这个方案是由 xpcs 同学在TesterHome社区网站的分享。 写在前面 去年11月被裁&#xff0c;到现在还没上岸&#xff0c;gap 半年了。上岸无望&#xff0c;专业技能不能落下&#xff0c;花了两三天时间&…

Linux之gdb的收尾部分

Linux之gdb的收尾部分 gbc常见指令的使用 gdb的调试

数据冒险-add x1, x1, x2 add x1, x1, x3 add x1, x1, x4

第一张图没有传递机制 竞争情况分析 读后写&#xff08;RAW&#xff09;竞争&#xff1a;当某条指令需要读取一个寄存器的值&#xff0c;而该寄存器的值尚未被前面的指令写入时&#xff0c;就会发生这种竞争。 指令2&#xff08;dadd r1, r1, r3&#xff09;依赖于指令1&#…

[产品管理-61]:马斯洛需求层次与产品的情感化设计

目录 一、概述 1、马斯洛需求层次理论概述 2、产品情感化设计与马斯洛需求层次的关系 3、产品情感化设计的实践案例 二、马斯洛需求层次与用户情感程度&#xff08;本能、行为、反思&#xff09;的关系 1、马斯洛需求层次与用户情感程度概述 2、马斯洛需求层次与用户情感…

浮动路由:实现出口线路的负载均衡冗余备份。

浮动路由 Tip&#xff1a;浮动路由指在多条默认路由基础上加入优先级参数&#xff0c;实现出口线路冗余备份。 ip routing-table //查看路由表命令 路由优先级参数&#xff1a;越小越优 本次实验测试两条默认路由&#xff0c;其中一条默认路由添加优先级参数&#xff0c;设置…

一阶 RC 低通滤波器实验方案

一阶 RC 低通滤波电路采用 RC 串联电路&#xff0c;把 R 或 C 做为负载端&#xff0c;对负载端与输入端的信 号做比较得到电路的特性曲线。图 1 所示 RC 串联电路构成一个双口网络&#xff0c; 根据图 1&#xff0c;其负载端开路时电容电压对输入电压的转移电压比为 这是一个…

华为私有接口类型hybrid

华为私有接口类型hybrid Tip&#xff1a;hybrid类型&#xff0c;简称混合型接口。 本次实验模拟2层网络下 vlan10 vlan20 不能互访&#xff0c;vlan10 vlan20 同时可以访问vlan100 sw1配置如下&#xff1a; <Huawei>sy [Huawei]sys sw1 [sw1]vl ba 10 20 100 [sw1]int…

006— 爬取第一考试网试题

import requests import logging import parsel import re import os#京东异步加载的反爬要求提供origin的信息 headers {user-agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.87 Safari/537.36 SE 2.X MetaSr 1.0}lo…

【分布式】分布式锁设计与Redisson源码解析

分布式锁 分布式锁是一种在分布式计算环境中用于控制多个节点&#xff08;或多个进程&#xff09;对共享资源的访问的机制。在分布式系统中&#xff0c;多个节点可能需要协调对共享资源的访问&#xff0c;以防止数据的不一致性或冲突。分布式锁允许多个节点在竞争访问共享资源…