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.rhkb.cn/news/467661.html

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

相关文章

PH热榜 | 2024-11-08

DevNow 是一个精简的开源技术博客项目模版&#xff0c;支持 Vercel 一键部署&#xff0c;支持评论、搜索等功能&#xff0c;欢迎大家体验。 在线预览 1. Quorini 标语&#xff1a;几分钟内设计并运行无服务器云 API 介绍&#xff1a;Quorini 提供了一套可视化的工具&#xff…

QML:Menu详细使用方法

目录 一.性质 二.作用 三.方法 四.使用 1.改变标签 2.打开本地文件 3.退出程序 4.打开Dialog 五.效果 六.代码 在 QML 中&#xff0c;Menu 是一个用于创建下拉菜单或上下文菜单的控件。它通常由多个 MenuItem 组成&#xff0c;每个 MenuItem 可以包含文本、图标和快捷…

k8s 处理namespace删除一直处于Terminating —— 筑梦之路

问题现象 k8s集群要清理某个名空间&#xff0c;把该名空间下的资源全部删除后&#xff0c;删除名空间&#xff0c;一直处于Terminating状态&#xff0c;无法完全清理掉。 如何处理 为什么要记录下这个处理的步骤&#xff0c;经过查询资料&#xff0c;网上也有各种各样的方法&…

>>,<<,~,,|,∧

‌监视器中的数值在十六进制显示时没有负数&#xff0c;主要是因为十六进制本身不直接表示负数&#xff0c;而是通过补码的形式来表示。

【韩老师零基础30天学会Java 】03章 变量

第三章 变量 1. 变量介绍 为什么需要变量&#xff1f; 变量是程序的基本组成单位 变量有三个基本单位&#xff1a;类型名称值 //1.定义变量int age 20;double score88.6;char gender男;String namejack;变量使用注意事项 变量表示内存中的一个存储区域[不同的变量,类型不同&am…

扭蛋机小程序开发,潮玩扭蛋机市场下新机遇

随着大众对潮玩文化的需求不断增长&#xff0c;市场进行了创新升级&#xff0c;不再局限于传统的销售营销模式&#xff0c;进一步推动行业的发展。目前&#xff0c;扭蛋机的种类越来越丰富&#xff0c;从手办、玩具到各种IP周边等&#xff0c;为市场带来更多新颖的扭蛋商品。销…

Unity 实现数字垂直滚动效果

Unity 实现数字垂直滚动效果 前言项目场景布置Shader代码编写材质球设置代码编写数字图片 前言 遇到一个需要数字垂直滚动模拟老虎机的效果&#xff0c;记录一下。 项目 场景布置 3个Image换上带有RollNumberShader的材质 在RollNumberScript脚本中引用即可 Shader代码编…

记录解决vscode 登录leetcode中遇到的问题

1. 安装完 leetcode 点击sign in to leetcode 点击打开网站登录leetcode&#xff0c;发现网页无法打开。 解决办法&#xff1a;将leetcode.cn.js文件中的leetcode-cn.com路径都改成leetcode.cn 2. 继续点击 sign in to leetcode &#xff0c;选择使用账号登录&#xff0c;始…

设计模式之适配器模式(从多个MQ消息体中,抽取指定字段值场景)

前言 工作到3年左右很大一部分程序员都想提升自己的技术栈&#xff0c;开始尝试去阅读一些源码&#xff0c;例如Spring、Mybaits、Dubbo等&#xff0c;但读着读着发现越来越难懂&#xff0c;一会从这过来一会跑到那去。甚至怀疑自己技术太差&#xff0c;慢慢也就不愿意再触碰这…

万字长文解读深度学习——循环神经网络RNN、LSTM、GRU、Bi-RNN

推荐阅读&#xff1a; 深度学习知识点全面总结 如何从RNN起步&#xff0c;一步一步通俗理解LSTM 深度学习之RNN(循环神经网络) 循环神经网络&#xff08;RNN与LSTM&#xff09; 文章目录 &#x1f33a;深度学习面试八股汇总&#x1f33a;文本特征提取的方法1. 基础方法1.1 词袋…

Qt 使用QTreeView显示并动态的增删改查JSON文件数据

文章目录 效果图概述部分代码总结 效果图 概述 本案例在此开源项目QJsonModel的基础上实现&#xff0c;动态的生成并操作JSON数据&#xff0c;QJsonModel是一个基于QAbstractItemModel的JSON数据模型&#xff0c;它提供了一种简单的方式来将JSON数据可视化&#xff0c;功能简单…

基于Springboot+Vue的游乐园管理系统 (含源码数据库)

1.开发环境 开发系统:Windows10/11 架构模式:MVC/前后端分离 JDK版本: Java JDK1.8 开发工具:IDEA 数据库版本: mysql5.7或8.0 数据库可视化工具: navicat 服务器: SpringBoot自带 apache tomcat 主要技术: Java,Springboot,mybatis,mysql,vue 2.视频演示地址 3.功能 该系统…

漫谈MCU优化:从硬件设计优化到可靠性挑战

1.关于MCU 微控制器&#xff08;Microcontroller Unit, MCU&#xff09;&#xff0c;是以微处理器为基础&#xff0c;加上存储器以及计数器、I2C、UART等外设模块与接口电路整合的单芯片微型计算机。 ▲MCU实物图 MCU拥有性能好、可编程、灵活度高、功耗低等优点&#xff0c;…

【深度学习】— 多输入多输出通道、多通道输入的卷积、多输出通道、1×1 卷积层、汇聚层、多通道汇聚层

【深度学习】— 多输入多输出通道、多通道输入的卷积、多输出通道、11 卷积层、汇聚层、多通道汇聚层 多输入多输出通道多通道输入的卷积示例&#xff1a;多通道的二维互相关运算 多输出通道实现多通道输出的互相关运算 11 卷积层11 卷积的作用 使用全连接层实现 11 卷积小结 …

如何在c++侧编译运行一个aclnn(AOL)算子?

1 AOL算子库 CANN&#xff08;Compute Architecture for Neural Networks&#xff09;提供了算子加速库&#xff08;Ascend Operator Library&#xff0c;简称AOL&#xff09;。该库提供了一系列丰富且深度优化过的高性能算子API&#xff0c;更亲和昇腾AI处理器&#xff0c;调…

IDEA git提交时如何忽略某个文件或文件夹

步骤如下 英文界面操作顺序 打开file——>settings——>Editor——>File Types 中文插件操作顺序 打开 文件——>设置——>编辑器——> 文件类型 安装下面的操作顺序添加想要屏蔽文件类型后缀即可&#xff1a;

《常用深度学习神经网络及其原理与应用场景》

一、总体介绍 一、引言 随着科技的不断发展&#xff0c;深度学习已经成为人工智能领域中最具影响力的技术之一。深度学习神经网络通过模拟人类大脑的神经元结构和工作方式&#xff0c;能够自动学习数据中的特征和模式&#xff0c;从而实现各种复杂的任务&#xff0c;如图像识…

科技革命前沿:救援机器人!

救援机器人主要制作材料 传统刚性材料&#xff1a;传统救援机器人多采用金属等刚性材料制作&#xff0c;以确保其结构强度和稳定性。这些材料在承受较大负载和复杂环境时表现出色&#xff0c;但可能缺乏一定的灵活性。 软体材料&#xff1a;近年来&#xff0c;软体机器人技术…

Ubuntu中以root身份运行Qt创建的项目

Ubuntu中以root身份运行Qt创建的项目 Chapter1 Ubuntu中以root身份运行Qt创建的项目解决方法&#xff1a; Chapter1 Ubuntu中以root身份运行Qt创建的项目 原文链接&#xff1a;https://blog.csdn.net/lhbaba/article/details/124733323 使用Qt开发项目时遇到了一个问题&#…

leetcode25:k个一组链表反转

给你链表的头节点 head &#xff0c;每 k 个节点一组进行翻转&#xff0c;请你返回修改后的链表。 k 是一个正整数&#xff0c;它的值小于或等于链表的长度。如果节点总数不是 k 的整数倍&#xff0c;那么请将最后剩余的节点保持原有顺序。 你不能只是单纯的改变节点内部的值…