C++连接mysql(改进)

使用vs2019对window11中的数据库进行连接

1. 配置连接环境

首先需要把mysql中的头文件和库文件放入到c++项目工程中

1.打开安装MySQL的目录,在windows系统中如果是默认路径,应该和我的是一样的:C:\Program Files\MySQL\MySQL Server 8.0

2.找到include,和lib文件,include文件是包含的头文件,lib文件是包含的库文件

3.在创建的c++工程中加入include,lib文件路径,按一下步骤

1.工程中的项目找到属性

2.到 VC++ 目录 中的包含目录和库目录分别加入include文件和lib文件的路径,

这是我的路径:include文件路径:C:\Program Files\MySQL\MySQL Server 8.0\include

lib文件路径:C:\Program Files\MySQL\MySQL Server 8.0\lib

3. 到 链接器 中的 输入 中的 附加依赖项中 加入 libmysql.lib 的依赖:

4.还需要把下图中的 libmysql.dll 的文件复制到 C:\Windows\System32 目录中

连接mysql可以参考 mysql参考手册 进行查看

2.代码实现连接

例子:

#define _CRT_SECURE_NO_WARNINGS#include<stdio.h>#include<mysql.h>#include<time.h>#include<stdlib.h>intmain(){
	int sr;
	srand((unsigned)time(NULL));
	sr = rand() % 50 + 1;
	//固定不变的
	MYSQL mysql;    //一个数据库结构体  
	MYSQL_RES* res; //一个结果集结构体
	MYSQL_ROW row; //char** 二维数据,存放一条条记录
	//初始化数据库
	mysql_init(&mysql);
	//设置编码方式
	mysql_options(&mysql, MYSQL_SET_CHARSET_NAME, "gbk");

	//连接数据库                    //ip地址	   //用户名 //密码       //数据库名
	if (mysql_real_connect(&mysql, "localhost", "root", "Z20020803", "box_man", 3306, NULL, 0) == NULL)
	{
		printf("错误原因:%s\n", mysql_error(&mysql));
		printf("连接失败\n");
		exit(-1);
	}
	//往数据库中插入一个随机数
	char* str1 = "insert into rand values(";
	char sql_insert[200];
	sprintf(sql_insert, "%s%d%s", str1, sr, ")");
	mysql_query(&mysql, sql_insert); //sql语句提交
	//查询数据
	mysql_query(&mysql, "select * from rand");
	//获取结果集
	res = mysql_store_result(&mysql);
	//给ROW赋值,判断ROW是否为空,不为空就打印数据
	while (row = mysql_fetch_row(res))
	{
		printf("%s\n", row[0]);
	}
	//释放结果集
	mysql_free_result(res);
	//关闭数据库
	mysql_close(&mysql);
	//停留等待
	system("pause");
	return0;

}

使用c++语句对数据库进行增删改查,在使用c++中string类型时,需要把string类型转换为c中的类型,使用mysql_query函数把sql语句提交,查询成功返回0,结果会被保存到mysql对象中,查询失败会返回非0值:

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<mysql.h>
#include<string>
usingnamespace std;

intmain(){
	MYSQL mysql;
	MYSQL_RES* res;
	MYSQL_ROW row;

	mysql_init(&mysql);


	if (mysql_real_connect(&mysql, "localhost", "root", "Z20020803", "box_man", 3306, NULL, 0) == NULL)
	{
		printf("错误提示:%s\n", mysql_error(&mysql));
		printf("连接失败\n");
	}
	//设置字符集
	mysql_options(&mysql, MYSQL_SET_CHARSET_NAME, "gbk");

	string str1 = "alter table tb_77 modify sex varchar(20)";//修改表类型失败
	mysql_query(&mysql, str1.c_str());
	string str = "insert into tb_77 values(5,'sdmqy','h')";//增加数据成功,不可以增加汉字
	mysql_query(&mysql, str.c_str());
	printf("%s", str.c_str());
	string str2 = "delete from tb_77 where sex = '女';";//删除数据成功
	mysql_query(&mysql, str2.c_str());
	string str3 = "update tb_77 set name = 'ttb' where id = 2";//更改也行
	mysql_query(&mysql, str3.c_str());


	mysql_close(&mysql);



	return0;
}

3.各个类说明:

1. mysql句柄类(是一个结构体)

1

MYSQL mysql;

该类在c++中操作数据库都要使用到

结构体原型:

typedef struct MYSQL {
  NET net;                     /* Communication parameters */
  unsigned char *connector_fd; /* ConnectorFd for SSL */
  char *host, *user, *passwd, *unix_socket, *server_version, *host_info;
  char *info, *db;
  struct CHARSET_INFO *charset;
  MYSQL_FIELD *fields;
  struct MEM_ROOT *field_alloc;
  uint64_t affected_rows;
  uint64_t insert_id;      /* id if insert on table with NEXTNR */
  uint64_t extra_info;     /* Not used */
  unsigned long thread_id; /* Id for connection in server */
  unsigned long packet_length;
  unsigned int port;
  unsigned long client_flag, server_capabilities;
  unsigned int protocol_version;
  unsigned int field_count;
  unsigned int server_status;
  unsigned int server_language;
  unsigned int warning_count;
  struct st_mysql_options options;
  enum mysql_status status;
  enum enum_resultset_metadata resultset_metadata;
  bool free_me;   /* If free in mysql_close */
  bool reconnect; /* set to 1 if automatic reconnect */

  /* session-wide random string */
  char scramble[SCRAMBLE_LENGTH + 1];

  LIST *stmts; /* list of all statements */
  const struct MYSQL_METHODS *methods;
  void *thd;
  /*
    Points to boolean flag in MYSQL_RES  or MYSQL_STMT. We set this flag
    from mysql_stmt_close if close had to cancel result set of this object.
  */
  bool *unbuffered_fetch_owner;
  void *extension;
} MYSQL;

2.MYSQL_RES查询结果集(是一个结构体)

2

MYSQL_RES * res=nullptr;

用来保存查询到的所有结果

结构体原型:

typedef struct MYSQL_RES {
  uint64_t row_count;
  MYSQL_FIELD *fields;
  struct MYSQL_DATA *data;
  MYSQL_ROWS *data_cursor;
  unsigned long *lengths; /* column lengths of current row */
  MYSQL *handle;          /* for unbuffered reads */
  const struct MYSQL_METHODS *methods;
  MYSQL_ROW row;         /* If unbuffered read */
  MYSQL_ROW current_row; /* buffer to current row */
  struct MEM_ROOT *field_alloc;
  unsigned int field_count, current_field;
  bool eof; /* Used by mysql_fetch_row */
  /* mysql_stmt_close() had to cancel this result */
  bool unbuffered_fetch_cancelled;
  enum enum_resultset_metadata metadata;
  void *extension;
} MYSQL_RES;

3.MYSQL_ROW获取结果集中的内容:本质上是一个char类型的二级指针

3.

MYSQL_ROW row

该变量可以获取到结果集中的数据

4.MYSQL_FIELD获取结果集中表的所有内容(是一个结构体)

结构体原型:

typedef struct MYSQL_FIELD {
  char *name;               /* Name of column */
  char *org_name;           /* Original column name, if an alias */
  char *table;              /* Table of column if column was a field */
  char *org_table;          /* Org table name, if table was an alias */
  char *db;                 /* Database for table */
  char *catalog;            /* Catalog for table */
  char *def;                /* Default value (set by mysql_list_fields) */
  unsigned long length;     /* Width of column (create length) */
  unsigned long max_length; /* Max width for selected set */
  unsigned int name_length;
  unsigned int org_name_length;
  unsigned int table_length;
  unsigned int org_table_length;
  unsigned int db_length;
  unsigned int catalog_length;
  unsigned int def_length;
  unsigned int flags;         /* Div flags */
  unsigned int decimals;      /* Number of decimals in field */
  unsigned int charsetnr;     /* Character set */
  enum enum_field_types type; /* Type of field. See mysql_com.h for types */
  void *extension;
} MYSQL_FIELD;

4.一些函数说明

mysql的使用手册网址:MySQL :: MySQL 8.0 C API 开发人员指南 :: 5.4.23 mysql_field_count()

部分API函数

函数

作用

mysql_init()

获取或初始化MYSQL结构。

mysql_real_connect()

连接到MySQL服务器。

mysql_query()

执行指定为“以Null终结的字符串”的SQL查询。

mysql_store_result()

检索完整的结果集至客户端。

mysql_use_result()

初始化逐行的结果集检索

mysql_fetch_field()

返回下一个表字段的类型。

mysql_fetch_fields()

返回所有字段结构的数组。

mysql_fetch_lengths()

返回当前行中所有列的长度。

mysql_fetch_row()

从结果集中获取下一行

mysql_field_count()

返回上次执行语句的结果列的数目。

mysql_free_result()

释放结果集使用的内存。

mysql_close()

关闭服务器连接。

mysql_autocommit()

切换 autocommit模式,ON/OFF

mysql_commit()

提交事务。

mysql_errno()

返回上次调用的MySQL函数的错误编号

mysql_options()

为mysql_connect()设置连接选项

mysql_ping()

检查与服务器的连接是否工作,如有必要重新连接。

在下列函数中,从连接数据库到获取数据库中的数据主要使用到1-7的函数。

1.mysql_init函数:初始化MYSQL变量

函数原型:

MYSQL *mysql_init(MYSQL *mysql) 
    说明:
        1.如果mysql是NULL指针,该函数将分配、初始化、并返回新对象。
        2.否则,将初始化对象,并返回对象的地址。
        3.如果mysql_init()分配了新的对象,应当在程序中调用mysql_close() 来关闭连接,以释放对象
    参数解释:
    返回值:初始化的MYSQL*句柄。如果无足够内存以分配新的对象,返回NULL。 
错误,在内存不足的情况下,返回NULL
    
2.mysql_read_connect函数:使用该函数连接mysql数据库

函数原型:

mysql_real_connect(
    MYSQL *mysql,   ///< 数据库句柄
    constchar *host, ///< 主机名
    constchar *user, ///< 用户名
    constchar *passwd,///< 密码
    constchar *db, ///< 数据库名
    unsignedint port, ///< 端口号(MySQL为3306)
    constchar *unix_socket,///< unix_socket–unix连接方式,为NULL时表示不使用socket或管道机制
    unsignedlong clientflag ///< clientflag–Mysql运行为ODBC数据库的标记,一般取0,该参数可以设置提交的sql语句为多条语句
    );

    作用:连接数据库引擎,通过函数mysql_real_connect()尝试与运行在主机上的MySQL数据库引擎建立连接。
    返回值:如果连接成功,返回MYSQL*连接句柄。如果连接失败,返回NULL。对于成功的连接,返回值与第1个参数的值相同。
3.mysql_real_query和mysql_query函数:进行数据库查询(也就是递交sql语句)

函数原型:

int STDCALL mysql_real_query(MYSQL *mysql, const char *query, unsigned long length);
    说明:执行由“Null终结的字符串”查询指向的SQL查询。
正常情况下,字符串必须包含1条SQL语句,而且不应为语句添加终结分号(‘;’)或“\g”。
如果允许多语句执行,字符串可包含多条由分号隔开的语句。(“多查询执行的C API处理”)mysql_query()
不能用于包含二进制数据的查询,应使用mysql_real_query()取而代之(二进制数据可能包含字符‘\0’,
mysql_query()会将该字符解释为查询字符串结束)。如果希望了解查询是否应返回结果集,
可使用mysql_field_count()进行检查。
    返回值:如果查询成功,返回0。如果出现错误,返回非0值。


int mysql_query(MYSQL *mysql, const char *query) 
    返回值:如果查询成功,返回0。如果出现错误,返回非0值。

    参数解释:
        参数mysql:前面使用MYSQL结构体定义的变量;
        参数query:sql语句
        参数length:sql语句的长度
4.mysql_store_result和mysql_use_result函数:获取查询结果数据

函数原型:

MYSQL_RES *mysql_store_result(MYSQL *mysql) 

    说明:
        1.对于成功检索了数据的每个查询(SELECT、SHOW、DESCRIBE、EXPLAIN、CHECK TABLE等)
    ,必须调用mysql_store_result()或mysql_use_result() 。
        2.如果希望了解查询是否应返回结果集,可使用mysql_field_count()进行检查。
        3.如果查询未返回结果集,mysql_store_result()将返回Null指针(例如,
    如果查询是INSERT语句)。
        4.如果读取结果集失败,mysql_store_result()还会返回Null指针。通过检查mysql_error()
    是否返回非空字符串,mysql_errno()是否返回非0值,或mysql_field_count()是否返回0,
    可以检查是否出现了错误。
        5.如果未返回行,将返回空的结果集。(空结果集设置不同于作为返回值的空指针)。
        6.一旦调用了mysql_store_result()并获得了不是Null指针的结果,可调用
    mysql_num_rows()来找出结果集中的行数。
        7.可以调用mysql_fetch_row()来获取结果集中的行,或调用mysql_row_seek()和
    mysql_row_tell()来获取或设置结果集中的当前行位置。
        8.一旦完成了对结果集的操作,必须调用mysql_free_result()。

    返回值:具有多个结果的MYSQL_RES结果集合。如果出现错误,返回NULL。


MYSQL_RES *  mysql_use_result(MYSQL *mysql);
    
    说明:调用mysql_use_result初始化检索,以便于后面一行一行的读取结果集,而它本身并没有从
服务器读取任何数据,这种方式较之第一种速度更快且所需内存更少,但它会绑定服务器,阻止其他线程
更新任何表,而且必须重复执行mysql_fetch_row读取数据,直至返回NULL,否则未读取的行会在下一
次查询时作为结果的一部分返回,故经常我们使用mysql_store_result。
5.mysql_fetch_row函数:读取结果集数据

函数原型:

MYSQL_ROW mysql_fetch_row(MYSQL_RES* result)
    说明:
        1.在mysql_store_result()之后使用时,如果没有要检索的行,mysql_fetch_row()返回NULL。
        2.在mysql_use_result()之后使用时,如果没有要检索的行或出现了错误,
    mysql_fetch_row()返回NULL。
        3.行内值的数目由mysql_num_fields(result)给出。如果行中保存了调用
    mysql_fetch_row()返回的值,将按照row[0]到row[mysql_num_fields(result)-1],
    访问这些值的指针。
        4.可以通过调用mysql_fetch_lengths()来获得行中字段值的长度。对于空字段以及
    包含NULL的字段,长度为0。通过检查字段值的指针,能够区分它们。如果指针为NULL,
    字段为NULL,否则字段为空。

    参数:是函数mysql_store_result或mysql_use_result的返回值

    返回值:下一行的MYSQL_ROW结构。如果没有更多要检索的行或出现了错误,返回NULL。
6.mysql_free_result函数:释放结果集

函数原型:

void mysql_free_result(MYSQL_RES *result) 
    说明:释放由mysql_store_result()、mysql_use_result()、mysql_list_dbs()等为结果
集分配的内存。完成对结果集的操作后,必须调用mysql_free_result()释放结果集使用的内存。
   
7.mysql_close函数:关闭数据库连接

函数原型:

void mysql_close(MYSQL *mysql) 
    说明:关闭前面打开的连接。如果句柄是由mysql_init()或mysql_connect()自动分配的,
mysql_close()还将解除分配由mysql指向的连接句柄。
8.mysql_num_fields(MYSQL_RES*):该函数可以拿表中的列数,返回值是一个unsigned类型

函数原型:

unsigned int STDCALL mysql_num_fields(MYSQL_RES *res);
9.mysql_fetch_fields(MYSQL_RES*): 该函数可以拿到表中每一列的字段名,返回的是一个结构体数组

函数原型:

MYSQL_FIELD *STDCALL mysql_fetch_fields(MYSQL_RES *res);
10.mysql_fetch_lengths(MYSQL_RES*):该函数拿到行中每一列的字段长度,返回结果是一个unsigned类型

函数原型:

unsigned long *STDCALL mysql_fetch_lengths(MYSQL_RES *result);
11.mysql_field_count函数:返回最近查询的列数 。

函数原型:

unsigned int mysql_field_count(MYSQL *mysql) 
    说明:此函数的正常用法是当返回 mysql_store_result() 时(因此您没有结果集) 指针)。
在这种情况下,您可以调用 mysql_field_count() 来 确定 mysql_store_result() 
是否应 产生了非空的结果

5.事务设置:

在mysql中事务是默认自动提交的,如果需要提交的事务多,对我们的操作会有影响,所以需要设置事务为手动提交

  • mysql_autocommit(MYSQL* , mode) 设置事务是否自动提交函数

参数:mode如果为“1”,自动提交,为“0”为手动提交 返回值:提交成功返回0,否则返回非0

  • mysql_commit(MYSQL* mysql) 事务提交函数

返回值:成功返回0,否则返回非0

  • mysql_rollback(MYSQL* mysql) 事务回滚函数

返回值:成功返回0,否则返回非0

6.打印错误信息:

  • const char* mysql_error(MYSQL* mysql):返回错误信息的描述

  • const char* mysql_errno(MYSQL* mysql):返回错误的编号

代码使用的例子

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<mysql.h>
usingnamespace std;

intmain(){
	//创建句柄
	MYSQL mysql;
	//创建数据集变量
	MYSQL_RES* res = nullptr;
	//创建结果集变量
	MYSQL_ROW row;
	//创建一个结构体
	MYSQL_FIELD* field;

	//初始化数据库句柄
	mysql_init(&mysql);
	//设置字符集
	//mysql_options(&mysql, MYSQL_SET_CHARSET_NAME, "gbk");
	mysql_set_character_set(&mysql, "gbk");
	//开始连接数据库
	if (mysql_real_connect(&mysql, "localhost", "root", "Z20020803", "box_man", 3306, NULL, 0))
	{
		cout << "连接成功" << endl;
	}
	else
	{
		cout << "连接失败" << endl;
		return0;
	}
	//设置事务
	mysql_autocommit(&mysql, "1");
	//增加数据
	string str1 = "insert into tb_912 values(2, 'xiaoming', '李四');";
	char ssql[1024];
	//使用sprintf拼出来的语句是一个标准的c语言字符串,可以使用该函数插入变量值
	sprintf(ssql, "insert into tb_912 values(%d, '%s', '%s');", 3, "daming", "17777777772");
	if (mysql_query(&mysql, ssql))//该语句提交成功返回0,失败返回1
	{
		cout << "提交失败" << endl;
	}
	else
	{
		cout << "提交成功" << endl;
	}
	//提交语句
	mysql_query(&mysql, str1.c_str());
	//删除数据
	string str3 = "delete from tb_912 where id = 2";
	mysql_query(&mysql, str3.c_str());
	//修改数据
	string str4 = "update tb_912 set name = '张三' where id = 1";
	mysql_query(&mysql, str4.c_str());
	//查询数据
	string str2 = "select * from tb_912";
	mysql_query(&mysql, str2.c_str());
	//事务提交
	mysql_commit(&mysql);
	//获取里面的结果集
	res = mysql_store_result(&mysql);
	//拿到结果集得列数,调用的是 mysql_store_result() 的返回值,
	unsignedint a = mysql_num_fields(res);
	cout <<"表得列数:"<< a << endl;
	//使用 mysql_fetch_fields() 函数获取列的名字,返回的是一个结构体数组
	field = mysql_fetch_fields(res);
	for (unsigned i = 0; i < a; i++)
	{
		cout << "当前列的名字:" << field[i].name << endl;//取出名字
	}
	unsignedlong* lengths;

	//从结果集中获取到数据 mysql_fetch_row() 获取结果集中的一行数据,
	//成功:返回记录当前行中每个字段的值,失败:返回一个null
	while (row = mysql_fetch_row(res))
	{
		printf("%s %s %s \n", row[0], row[1], row[2]);
		//获取列中字段的长度
		lengths = mysql_fetch_lengths(res);//返回的是一个数组地址
		
		for (unsignedint i = 0; i < a; i++)
		{
			cout << "当前列的长度:" << lengths[i] << endl;//列数会构成一个数组
		}
	}
	//释放结果集
	mysql_free_result(res);
	//关闭mysql实例
	mysql_close(&mysql);
	return0;
}

多条语句提交的代码实现

#include<iostream>
#include<mysql.h>
#include<thread>
#include<sstream>
#include<map>

using namespace std;

int main()
{
    //1.创建句柄
    MYSQL mysql;
    //2.初始化mysql
    mysql_init(&mysql);
    const char* host = "127.0.0.1";
    const char* user = "root";
    const char* pwd = "Z20020803";
    const char* db = "database1";

    //设定字符集
    mysql_options(&mysql, MYSQL_SET_CHARSET_NAME, "gbk");
    //3.连接数据库
    //一次性执行多条语句,mysql_real_connect 函数的最后一个参数设置
    if (!mysql_real_connect(&mysql, host, user, pwd, db, 3306, 0, CLIENT_MULTI_STATEMENTS))//阻塞函数
    {
        cout << "connect fail, " << mysql_error(&mysql) << endl;
    }
    else
    {
        cout << "mysql connect " << host << "success" << endl;
    }
    //1.创建表
    string sql = "CREATE TABLE IF NOT EXISTS t_image (\
        id int AUTO_INCREMENT,\
        name varchar(1024),\
        path varchar(1024),\
        size int,\
        PRIMARY KEY(id)\
        );";
    //2.删除数据
    sql += "truncate t_image;";
    //3.插入数据
    for (int i = 0; i < 1000; i++)
    {
        //sql = "insert t_image (name, path, size) values ('test.jpg', 'd:/img/test.jpg', 1024)";
        stringstream ss;//用于拼接字符串
        ss << "insert t_image (name, path, size) values ('image";
        ss << i << ".jpg', 'd:/image/',1024);";
        sql += ss.str();
    }
    //4.修改数据
    sql += "update t_image set name = 'test3.png', size = 100 where id = 3;";
    //5.删除数据
    sql += "delete from t_image where id = 1;";
    //6.查询数据
    sql += "select * form t_image;";

    //执行sql语句会立刻返回,但在数据库中是没有执行好的,需要获取结果
    int re = mysql_query(&mysql, sql.c_str());//只提交一次
    if (re == 0)
    {
        int count = mysql_affected_rows(&mysql);
        cout << "mysql_affected_rows " << count << "id = " << mysql_insert_id(&mysql) << endl;
    }
    else
    {
        cout << "mysql_query failed " << mysql_error(&mysql) << endl;
    }

    //多个返回结果
    do {
        MYSQL_RES* result = mysql_store_result(&mysql);
        if (result)
        {
            cout << "有select数据,行数:" << mysql_num_rows(result) << endl;
            mysql_free_result(result);//释放结果集
        }
        else//INSERT UPDATE DELETE CREATE DROP truncate
        {
            if (mysql_field_count(&mysql) > 0)//select 是否为空
            {
                cout << "Not retrieve result!" << mysql_error(&mysql) << endl;
            }
            else//INSERT UPDATE DELETE CREATE DROP truncate
            {
                //等待执行结果集
                cout << mysql_affected_rows(&mysql) << " rows affectd" << endl;
            }
        }
    } while (mysql_next_result(&mysql) == 0);//表示还有下一条结果
    mysql_close(&mysql);
    mysql_library_end();

    getchar();

    return 0;
}

图片的插入及获取

#include<iostream>
#include<mysql.h>
#include<thread>
#include<sstream>
#include<map>
#include<chrono>
#include<fstream>

using namespace std;
using namespace chrono;


int main()
{
    //1.创建句柄
    MYSQL mysql;
    //2.初始化mysql
    mysql_init(&mysql);
    const char* host = "127.0.0.1";
    const char* user = "root";
    const char* pwd = "Z20020803";
    const char* db = "database1";

    //设定字符集
    mysql_options(&mysql, MYSQL_SET_CHARSET_NAME, "gbk");
    //3.连接数据库
    if (!mysql_real_connect(&mysql, host, user, pwd, db, 3306, 0, CLIENT_MULTI_STATEMENTS))//阻塞函数
    {
        cout << "connect fail, " << mysql_error(&mysql) << endl;
    }
    else
    {
        cout << "mysql connect " << host << "success" << endl;
    }
    //1.创建表  使用了二进制的blob类型
    string sql = "CREATE TABLE IF NOT EXISTS t_data (\
        id int AUTO_INCREMENT,\
        name varchar(1024),\
        data blob,\
        size int,\
        PRIMARY KEY(id)\
        )ENGINE=InnoDB;";

    int re = mysql_query(&mysql, sql.c_str());
    if (re != 0)
    {
        cout << mysql_error(&mysql) << endl;
    }

    //2.清空表
    sql = "truncate t_data";
    re = mysql_query(&mysql, sql.c_str());
    if (re != 0)
    {
        cout << mysql_error(&mysql) << endl;
    }
    
    //3..创建stmt对象
    MYSQL_STMT* stmt = mysql_stmt_init(&mysql);
    if (!stmt)
    {
        cout << "mysql_stmt_init " << mysql_error(&mysql) << endl;
    }


    //4.预处理sql语句
    sql = "INSERT INTO t_data (name, data, size) VALUES(?,?,?)";
    if (mysql_stmt_prepare(stmt, sql.c_str(), sql.size()))
    {
        cerr << "mysql_stmt_prepare failed" << mysql_stmt_error(stmt) << endl;
    }

    //使用c++方式打开文件,也可以使用c语言的方式打开文件
    //5.打开文件
    string filename = "1.jpg";
    //文件大小和文件二进制地址
    int filesize = 0;
    //读取二进制
    fstream in(filename, ios::in | ios::binary);
    if (!in.is_open())
    {
        cerr << "file " << filename << " open failed!" << endl;
    }
    //文件指针移动到结尾处
    in.seekg(0, ios::end);
    //文件大小和文件二进制地址
    filesize = in.tellg();
    //文件指针回到开头
    in.seekg(0, ios::beg);

    //读取数据
    char* data = new char[filesize];
    int readed = 0;//已经读了多少
    while (!in.eof())
    {
        in.read(data + readed, filesize - readed);
        //读取了多少字节
        if (in.gcount() <= 0)
        {
            break;
        }
        readed += in.gcount();
    }
    in.close();


    //6.绑定字段
    MYSQL_BIND bind[3] = { 0 };
    bind[0].buffer_type = MYSQL_TYPE_STRING; //name 文件名
    bind[0].buffer = (char*)filename.c_str();
    bind[0].buffer_length = filename.size();

    bind[1].buffer_type = MYSQL_TYPE_BLOB;
    bind[1].buffer = data;
    bind[1].buffer_length = filesize;

    //文件大小
    bind[2].buffer_type = MYSQL_TYPE_LONG;
    bind[2].buffer = &filesize;

    //绑定stmt对象
    if (mysql_stmt_bind_param(stmt, bind) != 0)
    {
        cerr << "mysql_stmt_bind_param failed" << mysql_stmt_error(stmt) << endl;
    }

    //7.执行stmt sql
    if (mysql_stmt_execute(stmt) != 0)
    {
        cerr << "mysql_stmt_execute failed" << mysql_stmt_error(stmt) << endl;
    }

    delete data;
    mysql_stmt_close(stmt);

    //获取数据
    sql = "select * from t_data";
    re = mysql_query(&mysql, sql.c_str());
    if (re != 0)
    {
        cout << "mysql_store_result failed" << mysql_error(&mysql) << endl;
    }
    //获取结果集
    MYSQL_RES* res = mysql_store_result(&mysql);
    if (res == NULL)
    {
        cerr << "mysql_store_result failed" << mysql_error(&mysql) << endl;
    }
    //取一行数据
    MYSQL_ROW row = mysql_fetch_row(res);
    if (!row)
    {
        cerr << "mysql_fetch_row failed" << mysql_error(&mysql) << endl;
    }
    cout << row[0] << " " << row[1] << " " << row[2] << endl;
    //获取每一列字段的长度
    unsigned long* lens = mysql_fetch_lengths(res);
    int fnum = mysql_num_fields(res);//获取每一列的字段长度

    filename = "out_";
    filename += row[1];
    fstream out(filename, ios::out | ios::binary);
    if (!out.is_open())
    {
        cout << "open file " << filename << " failed" << endl;
    }
    out.write(row[2], lens[2]);
    out.close();


    mysql_close(&mysql);
    mysql_library_end();

    getchar();

    return 0;
}

存储过程的创建和使用

#include<iostream>
#include<mysql.h>
#include<thread>
#include<sstream>
#include<map>

using namespace std;

int main()
{
    //1.创建句柄
    MYSQL mysql;
    //2.初始化mysql
    mysql_init(&mysql);
    const char* host = "127.0.0.1";
    const char* user = "root";
    const char* pwd = "Z20020803";
    const char* db = "database1";

    //设定字符集
    mysql_options(&mysql, MYSQL_SET_CHARSET_NAME, "gbk");
    //3.连接数据库
    //一次性执行多条语句,mysql_real_connect 函数的最后一个参数设置
    if (!mysql_real_connect(&mysql, host, user, pwd, db, 3306, 0, CLIENT_MULTI_STATEMENTS))//阻塞函数
    {
        cout << "connect fail, " << mysql_error(&mysql) << endl;
    }
    else
    {
        cout << "mysql connect " << host << "success" << endl;
    }
    string sql = "";

    //1.创建存储过程
    sql = "CREATE PROCEDURE p_test(IN p_in INT, OUT p_out INT, INOUT p_inout INT)\
        BEGIN\
        select p_in, p_out, p_inout;\
        set p_in = 100, p_out = 200, p_inout = 300;\
        select p_in, p_out, p_inout;\
        END";
    int re = mysql_query(&mysql, sql.c_str());
    if (re != 0)
    {
        cout << mysql_error(&mysql) << endl;
    }
    //2.定义数据库的变量,并且赋值
    cout << "A = 1, B = 2, C = 3" << endl;
    sql = "SET @A=1;SET @B=2;SET @C=3;";
    re = mysql_query(&mysql, sql.c_str());
    if (re != 0)
    {
        cout << mysql_error(&mysql) << endl;
    }
    //需要获取结果集并且释放
    do
    {
        cout << "set affected " << mysql_affected_rows(&mysql) << endl;
    } while (mysql_next_result(&mysql) == 0);// 等于0表示还有结果,等于-1表示没有结果了,大于0表示出错

    //3.调用存储过程
    sql = "call p_test(@A,@B,@C)";
    re = mysql_query(&mysql, sql.c_str());
    if (re != 0)
    {
        cout << "select " << mysql_error(&mysql) << endl;
    }
    cout << "in proce:";
    do
    {
        MYSQL_RES* res = mysql_store_result(&mysql);
        if (!res)
        {
            continue;
        }
        //字段数量
        int fcount = mysql_num_fields(res);
        //打印结果集
        for (;;)
        {
            MYSQL_ROW row = mysql_fetch_row(res);
            if (!row)
            {
                break;
            }
            for (int i = 0; i < fcount; i++)
            {
                if (row[i])
                {
                    cout << row[i] << " ";
                }
                else
                {
                    cout << "NULL ";
                }
            }
            cout << endl;
        }
        mysql_free_result(res);
    } while (mysql_next_result(&mysql) == 0);

    //获取存储过程
    sql = "select @A,@B,@C";
    re = mysql_query(&mysql, sql.c_str());
    if (re != 0)
    {
        cout << mysql_error(&mysql) << endl;
    }
    MYSQL_RES* res1 = mysql_store_result(&mysql);
    MYSQL_ROW row = mysql_fetch_row(res1);
    int num = mysql_num_fields(res1);
    for (int i = 0; i < num; i++)
    {
        cout << row[i] << " ";
    }
    mysql_free_result(res1);
    
    
    mysql_close(&mysql);
    mysql_library_end();

    getchar();

    return 0;
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

某音上很火的圣诞树分享

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站。 效果截图&#xff08;这里不给动态了&#xff0c;某音到处都是了&#xff09;&#xff1a; 源代码&#xff1a; <script src"…

LeetCode-1008. 前序遍历构造二叉搜索树【栈 树 二叉搜索树 数组 二叉树 单调栈】

LeetCode-1008. 前序遍历构造二叉搜索树【栈 树 二叉搜索树 数组 二叉树 单调栈】 题目描述&#xff1a;解题思路一&#xff1a;题目大致意思就是给定一个二叉树的前序遍历&#xff0c;求对应的二叉搜索树。一种比较特殊的点是「二叉搜索树」的中序遍历的结果是【有序序列】&am…

智慧水利-城市水循环可视化助力城市水资源可持续发展

2021年《中华人民共和国国民经济和社会发展第十四个五年规划和2035年远景目标纲要》明确指出&#xff1a;构建智慧水利体系&#xff0c;以流域为单元提升水情测报和智能调度能力。水利部按照“需求牵引、应用至上、数字赋能、提升能力”总要求&#xff0c;编制了《“十四五”智…

深入理解强化学习——马尔可夫决策过程:预测与控制

分类目录&#xff1a;《深入理解强化学习》总目录 预测&#xff08;Prediction&#xff09;和控制&#xff08;Control&#xff09;是马尔可夫决策过程里面的核心问题。预测&#xff08;评估一个给定的策略&#xff09;的输入是马尔可夫决策过程 < S , A , R , P , γ > …

中职网络安全应急响应—Server2228

应急响应 任务环境说明: 服务器场景:Server2228(开放链接) 用户名:root,密码:p@ssw0rd123 1. 找出被黑客修改的系统别名,并将倒数第二个别名作为Flag值提交; 通过用户名和密码登录系统 在 Linux 中,利用 “alias” 命令去查看当前系统中定义的所有别名 flag:ss …

LeetCode:1631. 最小体力消耗路径(SPFA Java)

目录 1631. 最小体力消耗路径 题目描述&#xff1a; 实现代码与解析&#xff1a; BFSDP 原理思路&#xff1a; 1631. 最小体力消耗路径 题目描述&#xff1a; 你准备参加一场远足活动。给你一个二维 rows x columns 的地图 heights &#xff0c;其中 heights[row][col] 表…

python 爬虫 m3u8 视频文件 加密解密 整合mp4

文章目录 一、完整代码二、视频分析1. 认识m3u8文件2. 获取密钥&#xff0c;构建解密器3. 下载ts文件4. 合并ts文件为mp4 三、总结 一、完整代码 完整代码如下&#xff1a; import requests import re import os from tqdm import tqdm from Crypto.Cipher import AES# 创建临…

通过Jmeter压测存储过程

一、存储过程准备&#xff1a; 1、建立一个空表&#xff1a; 1 CREATE TABLE test_data ( id NUMBER, name VARCHAR2(50), age NUMBER ); 2、建立一个存储过程&#xff1a; CREATE OR REPLACE PROCEDURE insert_test_data(n IN NUMBER) ASBEGIN--EXECUTE IMMEDIATE trunca…

打工人副业变现秘籍,某多/某手变现底层引擎-Stable Diffusion 黑白老照片上色修复

在这个时代,我们习惯于拥有高清、色彩丰富的照片,然而,那些古老的黑白色老照片由于年代的久远,往往会出现模糊、破损等现象。 那么今天要给大家介绍的是,用 Stable Diffusion 来修复老照片。 前段时间 ControlNet 的除了上线了“IP-Adapter”模型以外还增加另一个…

JVM虚拟机系统性学习-对象存活判断算法、对象引用类型和垃圾清除算法

垃圾回收 在 JVM 中需要对没有被引用的对象&#xff0c;也就是垃圾对象进行垃圾回收 对象存活判断算法 判断对象存活有两种方式&#xff1a;引用计数法、可达性分析算法 引用计数法 引用计数法通过记录每个对象被引用的次数&#xff0c;例如对象 A 被引用 1 次&#xff0c…

决策报表布局方式(新建一个绝对布局,双击,在拖其它图表,报表块装进去。就不会变形)

FineReport11.0 1.绝对布局&#xff1a; 只是适合自己调试电脑显示&#xff0c;适用于一个展示区域需要用多个组件叠加组成时使用 2.自适应布局&#xff1a;双向自适应 &#xff1a; https://help.fanruan.com/finereport/doc-view-4276.html 组件会自动调整显示宽度以适应不…

实战React18和TS+Vite,跟进实战阅读类App的心得分享

随着 React 18 的发布&#xff0c;以及 TypeScript 和 Vite 在前端开发领域的普及&#xff0c;使用 React 18 结合 TypeScript 和 Vite 开发实战阅读类 App 的经验已经成为了前端开发者们的热门话题。在本文中&#xff0c;我将分享我的心得体会&#xff0c;并给出一些示例代码&…

12.11_黑马数据结构与算法笔记Java

目录 070 栈 链表实现 概念理清&#xff1a;什么时候是指针的指向&#xff0c;什么时候是元素本身&#xff1f; 071 栈 数组实现 072 栈 e01 有效的括号 072 栈 e02 后缀表达式求值 072 栈 e03 中缀表达式转后缀1 072 栈 e03 中缀表达式转后缀2 072 栈 e03 中缀表达式转…

Linux之进程(三)(环境变量)

目录 一、基本概念 二、环境变量 1、PATH 2、HOME 3、SHELL 三、环境变量参数 四、argc和argv 一、基本概念 环境变量(environment variables)一般是指在操作系统中用来指定操作系统运行环境的一些参数。如&#xff1a;临时文件夹位置和系统文件夹位置等。环境变量通常…

通用的AGI 安全风险

传统安全风险 平台基础设施安全风险 模型与数据层安全风险 应用层安全风险 平台基础设施安全风险 &#xff08;1&#xff09;物理攻击&#xff1a;机房管控不到位 &#xff08;2&#xff09;网络攻击 &#xff08;3&#xff09;计算环境&#xff1a;自身安全漏洞&#xf…

Java - Mybatis的缓存机制、集成SpringBoot后缓存相关问题

mybaits提供一级缓存&#xff0c;和二级缓存 一级缓存&#xff08;默认开启&#xff09; 一级缓存是SqlSession级别的缓存。在操作数据库时需要构造 sqlSession对象&#xff0c;在对象中有一个(内存区域)数据结构&#xff08;HashMap&#xff09;用于存储缓存数据。不同的sqlSe…

【Java SE】带你识别什么叫做异常!!!

&#x1f339;&#x1f339;&#x1f339;个人主页&#x1f339;&#x1f339;&#x1f339; 【&#x1f339;&#x1f339;&#x1f339;Java SE 专栏&#x1f339;&#x1f339;&#x1f339;】 &#x1f339;&#x1f339;&#x1f339;上一篇文章&#xff1a;【Java SE】带…

U5 符号表管理

文章目录 一、语义分析1、任务 二、符号表1、概述2、操作3、基本结构4、组织方式 三、非分程序的符号表1、概念2、标识符的作用域及基本处理办法3、符号表的组织方式 四、分程序的符号表&#xff1a;处理作用域嵌套1、概念2、处理方法 五、栈式符号表六、基于符号表的存储组织与…

Appilied energy论文复现:计及光伏电站快速无功响应特性的分布式电源优化配置方法程序代码!

本程序参考Applied energy论文《Optimal siting and sizing of distributed generation in distribution systems with PV solar farm utilized as STATCOM (PV-STATCOM)》&#xff0c;文中主要对光伏电站、微燃机等分布式电源进行优化配置&#xff0c;程序较为简单和基础&…

SD生成的图像不清晰,如何解决

文生图 选择高清修复&#xff1a; 几点注意 重绘幅度&#xff1a;这里不用太高&#xff0c;他会根据你生成的低分辨率图像&#xff0c;生成高分辨率的图像&#xff0c;可以选择0.3~05之间&#xff0c;给AI跟多想象力空间可以选择0.5 ~ 0.7。太低边缘模糊&#xff0c;太高了可能…