C++ connects to mysql (improved)

Use vs2019 to connect to the database in window11

1. Configure the connection environment

First, you need to put the header files and library files in mysql into the c++ project

1. Open the directory where MySQL is installed. If it is the default path in the windows system, it should be the same as mine: C:\Program Files\MySQL\MySQL Server 8.0

2. Find the include and lib files, the include file is the included header file, and the lib file is the included library file

3. Add include and lib file paths to the created c++ project, and click the steps

1. Find the properties of the project in the project

2. Go to the include directory and library directory in the VC++ directory and add the path of the include file and lib file respectively,

This is my path: include file path: C:\Program Files\MySQL\MySQL Server 8.0\include

lib file path: C:\Program Files\MySQL\MySQL Server 8.0\lib

3. Add the libmysql.lib dependency to the additional dependencies in the input of the linker:

4. You also need to copy the libmysql.dll file in the figure below to the C:\Windows\System32 directory

To connect to mysql, you can refer to the mysql reference manual for viewing

2. Code to achieve connection

example:

#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;

}

Use c++ statements to add, delete, modify, and query the database. When using the string type in c++, you need to convert the string type to the type in c, use the mysql_query function to submit the sql statement, and the query returns 0 successfully, and the result will be saved in the mysql object , if the query fails, a non-zero value will be returned:

#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. Description of each class:

1. mysql handle class (a structure)

1

MYSQL mysql;

This class is used in c++ to operate the database

Structure prototype:

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 query result set (a structure)

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;
}

Guess you like

Origin blog.csdn.net/weixin_62859191/article/details/128767283