C++ Mysql 工程搭建及基本操作笔记

C++ Mysql 工程搭建及基本操作笔记

目录

C++ Mysql 工程搭建及基本操作笔记

C++ Mysql 工程搭建

Mysql初始化

Mysql 连接及查询等基本操作

mysql_real_connect数据库完成连接,以及超时重连设置

语句查询示例

获取表字段及数量等信息 mysql_fetch_field,mysql_fetch_field_direct

表格创建及数据增删改查

一次执行多条sql语句

事务操作

比较单条和多条SQL语句及事务插入十万条数据的性

 二进制数据图片的读取并存储为文件

创建存储过程

C++ Mysql 工程搭建

  • 工程目录结构

  • 找到安装的mysql目录下的 include 和 lib,将其复制到代码工程目录下,这两个文件夹下有些不需要的可以删除。

  • 比如lib中只需要

  •  配置头文件路径:

  •  库目录:

  • 链接:

  • 设置输出目录

  • bin目录下需要添加相应的动态库,可以在mysql的bin目录下找到复制过来

  • 测试代码:
#include <iostream>
#include "mysql.h"

int main()
{
    MYSQL mysql;
    mysql_info(&mysql);

    std::cout << "Hello World!\n";
}

Mysql初始化

//初始化mysql上下文
//MYSQL mysql;
//单线程模式 mysql_init自动调用 线程不安全
mysql_library_init(0, 0, 0);

for (;;)
{
	//方式1
	//MYSQL mysql;
	//mysql_init(&mysql);
	//mysql_close(&mysql);
	
	//方式2
	//MYSQL *mysql = new MYSQL();
	//mysql_init(mysql);
	//mysql_close(mysql);
	//delete mysql;
	
	//方式3
	MYSQL *mysql = mysql_init(0);
	mysql_close(mysql);
}

mysql_library_end();

Mysql 连接及查询等基本操作

mysql_real_connect数据库完成连接,以及超时重连设置

#include "mysql.h"
#include <iostream>
#include <thread>
#include <chrono>

int main()
{
  //初始化mysql上下文
  MYSQL mysql;
  //单线程模式 mysql_init自动调用 mysql_library_init 线程不安全
  mysql_init(&mysql);
  const char *host = "127.0.0.1";
  const char *user = "root";
  const char *pass = "root";
  const char *db = "cpptest";  //数据库名称

  //设定超时3秒
  int to = 3;
  int re = mysql_options(&mysql, MYSQL_OPT_CONNECT_TIMEOUT, &to);
  if (re != 0) {
    std::cout << "mysql_options failed!" << mysql_error(&mysql) << std::endl;
  }
  //自动重连
  int recon = 1;
  re = mysql_options(&mysql, MYSQL_OPT_RECONNECT, &recon);
  if (re != 0) {
    std::cout << "mysql_options failed!" << mysql_error(&mysql) << std::endl;
  }

  if (!mysql_real_connect(&mysql, host, user, pass, db, 3306, 0, 0)) {
    std::cout << "mysql connect failed!" << mysql_error(&mysql) << std::endl;
  } else {
    std::cout << "mysql connect success!" << std::endl;
  }

  for (int i = 0; i < 1000; i++) {
  int re = mysql_ping(&mysql);
  if (re == 0) {
    std::cout << host << ":mysql ping success!" << std::endl;
  } else {
    std::cout << host << ":mysql ping failed! " << mysql_error(&mysql) << std::endl;
  }
    std::this_thread::sleep_for(std::chrono::seconds(1));
  }

  mysql_close(&mysql);
  mysql_library_end();

}

语句查询示例

// user select * from test1
// 1 执行SQL语句
const char *sql = "select * from test1";
// mysql_real_query  sql语句中可以包含二进制数据
// mysql_query sql语句中只能是字符串
// 0返回表示成功
int re = mysql_real_query(&mysql, sql, strlen(sql));

// Commands out of sync; you can't run this command now
// 执行sql语句后,必须获取结果集并且清理
// re = mysql_query(&mysql, sql);
if (re != 0) {
  std::cout << "mysql_real_query faied! " << sql << " " << mysql_error(&mysql)
       << std::endl;
} else {
  std::cout << "mysql_real_query success! " << sql << std::endl;
}

// 2 获取结果集
// mysql_use_result 不实际读取数据
// MYSQL_RES* result = mysql_use_result(&mysql);
// mysql_store_result 读取所有数据,注意缓存大小 MYSQL_OPT_MAX_ALLOWED_PACKET
// 默认 64M
MYSQL_RES *result = mysql_store_result(&mysql);
if (!result) {
  std::cout << "mysql_use_result faied! " << mysql_error(&mysql) << std::endl;
}

// 3 遍历结果集
MYSQL_ROW row;
while (row = mysql_fetch_row(result)) {
  unsigned long *lens = mysql_fetch_lengths(result);
  std::cout << lens[1] << "[" << row[0] << "," << row[1] << "]" << std::endl;
}

//清理结果集
mysql_free_result(result);

获取表字段及数量等信息 mysql_fetch_field,mysql_fetch_field_direct

MYSQL_RES *result = mysql_store_result(&mysql);
if (!result) {
  std::cout << "mysql_use_result faied! " << mysql_error(&mysql) << std::endl;
}
//获取表字段
MYSQL_FIELD *field = 0;
while (field = mysql_fetch_field(result)) {
  std::cout << "key:" << field->name << std::endl;
}

//获取表字段数量
int fnum = mysql_num_fields(result);
std::cout << "fnum = " << fnum << std::endl;

// 3 遍历结果集
MYSQL_ROW row;
while (row = mysql_fetch_row(result)) {
  unsigned long *lens = mysql_fetch_lengths(result);

  for (int i = 0; i < fnum; i++) {
    std::cout << mysql_fetch_field_direct(result, i)->name << ":";
    if (row[i])
      std::cout << row[i];
    else
      std::cout << "NULL";
    std::cout << ",";
  }
  std::cout << "\n" << std::endl;
}

//清理结果集
mysql_free_result(result);
  • 示例: 

表格创建及数据增删改查

// 1 创建表
std::string sql = "";
sql ="CREATE TABLE IF NOT EXISTS `t_image`  ( \
	`id` int AUTO_INCREMENT,\
	`name` varchar(1024),\
	`path` varchar(2046),\
	`size` int,\
	PRIMARY KEY(`id`)\
	) ";
int re = mysql_query(&mysql, sql.c_str());
if (re != 0) {
  std::cout << "CREATE TABLE failed!" << mysql_error(&mysql) << std::endl;
}

//清空数据,并恢复自增id从1开始
sql = "truncate t_image";
re = mysql_query(&mysql, sql.c_str());
if (re != 0) {
  std::cout << "truncate failed!" << mysql_error(&mysql) << std::endl;
}

// 2 插入数据 CLIENT_MULTI_STATEMENTS
for (int i = 0; i < 10; i++) {
  // sql = "insert `t_image` (`name`,`path`,`size`)
  // values('test.jpg','d:/img/test.jpg',10240)";
  std::stringstream ss;
  ss << "insert `t_image` (`name`,`path`,`size`) values('image";
  ss << i << ".jpg','d:/img/', 10240)";
  sql = ss.str();

  re = mysql_query(&mysql, sql.c_str());
  if (re == 0) {
    int count = mysql_affected_rows(&mysql);
    std::cout << "insert mysql_affected_rows " << count << std::endl;
  } else {
    std::cout << "insert failed!" << mysql_error(&mysql) << std::endl;
  }
}

// 3 修改数据
// update t_image set `name`="test2.png",size=2000 where id=1
sql = "update t_image set `name`='test114514.png',size=2000 where id=1";
re = mysql_query(&mysql, sql.c_str());
if (re == 0) {
  int count = mysql_affected_rows(&mysql);
  std::cout << "update mysql_affected_rows " << count << std::endl;
} else {
  std::cout << "update failed!" << mysql_error(&mysql) << std::endl;
}

//技巧:根据map自动生成 update sql语句
std::map<std::string, std::string> kv;
kv.insert(std::make_pair("name", "image_update001.png"));
kv.insert(std::make_pair("size", "5000"));
std::string where = " where id=2 ";
std::string tmp = "";
for (auto ptr = kv.begin(); ptr != kv.end(); ptr++) {
  tmp += "`";
  tmp += ptr->first;
  tmp += "`='";
  tmp += ptr->second;
  tmp += "',";
}
tmp += " id=id ";
sql = "update t_image set ";
sql += tmp;
sql += where;

re = mysql_query(&mysql, sql.c_str());
if (re == 0) {
  int count = mysql_affected_rows(&mysql);
  std::cout << "update mysql_affected_rows " << count << std::endl;
} else {
  std::cout << "update failed!" << mysql_error(&mysql) << std::endl;
}

// 4 删除数据
sql = "delete from t_image where id=1";
re = mysql_query(&mysql, sql.c_str());
if (re == 0) {
  int count = mysql_affected_rows(&mysql);
  std::cout << "delete mysql_affected_rows " << count << std::endl;
} else {
  std::cout << "delete failed!" << mysql_error(&mysql) << std::endl;
}

// delete 不会实际删除空间,只做了标识
sql = "delete from t_image";
re = mysql_query(&mysql, sql.c_str());
if (re == 0) {
  int count = mysql_affected_rows(&mysql);
  std::cout << "delete mysql_affected_rows " << count << std::endl;
} else {
  std::cout << "delete failed!" << mysql_error(&mysql) << std::endl;
}

//实际清理了空间,空闲时间进行操作
sql = "OPTIMIZE TABLE t_image";
re = mysql_query(&mysql, sql.c_str());

一次执行多条sql语句

 //初始化mysql上下文
 MYSQL mysql;
 //单线程模式 mysql_init自动调用 mysql_library_init 线程不安全
 mysql_init(&mysql);
 const char *host = "127.0.0.1";
 const char *user = "root";
 const char *pass = "root";
 const char *db = "cpptest";  //数据库名称

 // CLIENT_MULTI_STATEMENTS 支持多条sql语句
 if (!mysql_real_connect(&mysql, host, user, pass, db, 3306, 0,
                         CLIENT_MULTI_STATEMENTS))
 {
   std::cout << "mysql connect failed!" << mysql_error(&mysql) << std::endl;
 } else {
   std::cout << "mysql connect success!" << std::endl;
 }


	// 1 创建表
 std::string sql =
     "CREATE TABLE IF NOT EXISTS `t_image`  ( \
		`id` int AUTO_INCREMENT,\
		`name` varchar(1024),\
		`path` varchar(2046),\
		`size` int,\
		PRIMARY KEY(`id`)\
		) ;";

 //清空数据,并恢复自增id从1开始
 sql += "truncate t_image;";

 // 2 插入数据 CLIENT_MULTI_STATEMENTS
 for (int i = 0; i < 100; i++) {
   // sql = "insert `t_image` (`name`,`path`,`size`)
   // values('test.jpg','d:/img/test.jpg',10240)";
   std::stringstream ss;
   ss << "insert `t_image` (`name`,`path`,`size`)values('image";
   ss << i << ".jpg','d:/img/', 10240);";
   sql += ss.str();
 }

 // 3 修改数据
 // update t_image set `name`="test2.png",size=2000 where id=1
 sql += "update t_image set `name`='test3.png',size=2000 where id=1;";
 // 4 删除数据
 sql += "delete from t_image where id=1;";

 //查询结果
 sql += "select * from t_image;";

 //执行sql语句立刻返回,但语句并没有全部执行好,需要获取结果
 //把sql整个发送给mysql server,server一条条执行,返回结果
 int re = mysql_query(&mysql, sql.c_str());
 if (re != 0) {
   std::cout << "mysql_query failed!" << mysql_error(&mysql) << std::endl;
 }

 //有多个返回结果
 do {
   std::cout << "[result]";
   MYSQL_RES *result = mysql_store_result(&mysql);
   if (result)  // SELECT
   {
     std::cout << "SELECT mysql_num_rows = " << mysql_num_rows(result)
               << std::endl;
     mysql_free_result(result);
   } else  // INSERT UPDATE DELETE CREATE DROP truncate
   {
     // SELECT 出错 有字段无结果
     if (mysql_field_count(&mysql) > 0) {
       std::cout << "Not retrieve result! " << mysql_error(&mysql)
                 << std::endl;
     } else  // INSERT UPDATE DELETE CREATE DROP truncate
     {
       //等待服务器的处理结果
       std::cout << mysql_affected_rows(&mysql) << " rows affected!"
                 << std::endl;
     }
   }

 }//取下一条结果 0表示有结果
 while (mysql_next_result(&mysql) == 0);

事务操作

//创建表
  std::string sql =
      "CREATE TABLE IF NOT EXISTS `t_video`  ( \
		`id` int AUTO_INCREMENT,\
		`name` varchar(1024),\
		`path` varchar(2046),\
		`size` int,\
		PRIMARY KEY(`id`)\
		) ENGINE=InnoDB;";  //设置支持事务回滚的 InnoDB引擎
  int re = mysql_query(&mysql, sql.c_str());
  if (re != 0) {
    std::cout << "mysql_query failed! " << mysql_error(&mysql) << std::endl;
  }
  //清空数据,并恢复自增id从1开始
  //清理表数据
  sql = "truncate t_video";
  re = mysql_query(&mysql, sql.c_str());
  if (re != 0) {
    std::cout << "mysql_query failed! " << mysql_error(&mysql) << std::endl;
  }

  // 事务
  // 1 开始事务
  // START TRANSACTION;
  sql = "START TRANSACTION";
  re = mysql_query(&mysql, sql.c_str());
  if (re != 0) {
    std::cout << "mysql_query failed! " << mysql_error(&mysql) << std::endl;
  }

  // 2 设置为手动提交事务
  // set autocommit = 0
  sql = "set autocommit = 0";
  re = mysql_query(&mysql, sql.c_str());
  if (re != 0) {
    std::cout << "mysql_query failed! " << mysql_error(&mysql) << std::endl;
  }

  // 3 sql语句

  //插入三条数据,回滚
  for (int i = 0; i < 3; i++) {
    sql = "insert into t_video (name) values('test 111111!')";
    re = mysql_query(&mysql, sql.c_str());
    if (re != 0) {
      std::cout << "mysql_query failed! " << mysql_error(&mysql) << std::endl;
    }
  }

  // 4 回滚ROLLBACK MYISAM 不支持
  sql = "ROLLBACK";
  re = mysql_query(&mysql, sql.c_str());
  if (re != 0) {
    std::cout << "mysql_query failed! " << mysql_error(&mysql) << std::endl;
  }

  for (int i = 0; i < 1000; i++) {
    sql = "insert into t_video (name) values('test three!')";
    re = mysql_query(&mysql, sql.c_str());
    if (re != 0) {
      std::cout << "mysql_query failed! " << mysql_error(&mysql) << std::endl;
    }
  }

  // 5 COMMIT
  sql = "COMMIT";
  re = mysql_query(&mysql, sql.c_str());
  if (re != 0) {
    std::cout << "mysql_query failed! " << mysql_error(&mysql) << std::endl;
  }

  // 6 恢复自动提交 set autocommit = 1
  sql = "set autocommit = 1";
  re = mysql_query(&mysql, sql.c_str());
  if (re != 0) {
    std::cout << "mysql_query failed! " << mysql_error(&mysql) << std::endl;
  }

  //查询结果
  sql = "select count(*) from t_video";
  re = mysql_query(&mysql, sql.c_str());
  if (re != 0) {
    std::cout << "mysql_query failed! " << mysql_error(&mysql) << std::endl;
  }
  MYSQL_RES *res = mysql_store_result(&mysql);
  if (res) {
    //取得第一行数据
    MYSQL_ROW row = mysql_fetch_row(res);
    if (row) {
      std::cout << "t_video count(*) = " << row[0] << std::endl;
    }
  }

比较单条和多条SQL语句及事务插入十万条数据的性

  auto start = std::chrono::system_clock::now();
  	//单条语句插入1千条数据
  for (int i = 0; i < 1000; i++) {
    sql =
        "insert into t_video (name,path) "
        "values('single','"
        "01234567890123456789012345678901234567890123456789012345678901234567"
        "89012345678901234567890123456789')";
    re = mysql_query(&mysql, sql.c_str());
    if (re != 0) {
      std::cout << "mysql_query failed! " << mysql_error(&mysql) << std::endl;
    }
  }
  auto end = std::chrono::system_clock::now();
  //转换为毫秒 1000
  auto dur = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
  std::cout << "1 单条语句插入1千条数据" << dur.count() / 1000. << "秒"
            << std::endl;
 //多条语句插入1千条数据
  {
    auto start = std::chrono::system_clock::now();
    sql = "";
    //单条语句插入1千条数据
    for (int i = 0; i < 1000; i++) {
      sql +=
          "insert into t_video (name,path) "
          "values('single','"
          "01234567890123456789012345678901234567890123456789012345678901234567"
          "89012345678901234567890123456789');";
    }

    re = mysql_query(&mysql, sql.c_str());
    if (re != 0) {
      std::cout << "mysql_query failed! " << mysql_error(&mysql) << std::endl;
    }
    do {
      //std::cout << mysql_affected_rows(&mysql) << std::flush;
      mysql_affected_rows(&mysql);
    } while (mysql_next_result(&mysql) == 0);
    auto end = std::chrono::system_clock::now();
    //转换为毫秒 1000
    auto dur =
        std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
    std::cout << "2 多条语句插入1千条数据" << dur.count() / 1000. << "秒"
              << std::endl;
  }
  //事务插入1千条数据
  {
    // 1 开始事务
    // START TRANSACTION;
    sql = "START TRANSACTION";
    re = mysql_query(&mysql, sql.c_str());
    if (re != 0) {
      std::cout << "mysql_query failed! " << mysql_error(&mysql) << std::endl;
    }

    // 2 设置为手动提交事务
    // set autocommit = 0
    sql = "set autocommit = 0";
    re = mysql_query(&mysql, sql.c_str());
    if (re != 0) {
      std::cout << "mysql_query failed! " << mysql_error(&mysql) << std::endl;
    }

    auto start = std::chrono::system_clock::now();
    //单条语句插入1千条数据
    for (int i = 0; i < 1000; i++) {
      sql =
          "insert into t_video (name,path) "
          "values('single','"
          "01234567890123456789012345678901234567890123456789012345678901234567"
          "89012345678901234567890123456789')";
      re = mysql_query(&mysql, sql.c_str());
      if (re != 0) {
        std::cout << "mysql_query failed! " << mysql_error(&mysql) << std::endl;
      } else
        //std::cout << mysql_affected_rows(&mysql) << std::flush;
        mysql_affected_rows(&mysql);
    }

    sql = "COMMIT";
    re = mysql_query(&mysql, sql.c_str());
    if (re != 0) {
      std::cout << "mysql_query failed! " << mysql_error(&mysql) << std::endl;
    }
    sql = "set autocommit = 1";
    re = mysql_query(&mysql, sql.c_str());
    if (re != 0) {
      std::cout << "mysql_query failed! " << mysql_error(&mysql) << std::endl;
    }

    auto end = std::chrono::system_clock::now();
    //转换为毫秒 1000
    auto dur =
        std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
    std::cout << "3 事务插入1千条数据" << dur.count() / 1000. << "秒"
              << std::endl;
  }
  • 结果:

 二进制数据图片的读取并存储为文件

// mysqltest.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include "mysql.h"
#include <iostream>
#include <thread>
#include <chrono>
#include <sstream>
#include <map>
#include <fstream>

int main()
{
  //初始化mysql上下文
  MYSQL mysql;
  //单线程模式 mysql_init自动调用 mysql_library_init 线程不安全
  mysql_init(&mysql);
  const char *host = "127.0.0.1";
  const char *user = "root";
  const char *pass = "root";
  const char *db = "cpptest";  //数据库名称

  if (!mysql_real_connect(&mysql, host, user, pass, db, 3306, 0,
                          CLIENT_MULTI_STATEMENTS))
  {
    std::cout << "mysql connect failed!" << mysql_error(&mysql) << std::endl;
  } else {
    std::cout << "mysql connect success!" << std::endl;
  }

	// 1 创建好存放二进制数据的表 t_data
  std::string sql =
      "CREATE TABLE IF NOT EXISTS `t_data` (\
		`id` int AUTO_INCREMENT,\
		`name` varchar(1024),\
		`data` blob,\
		`size` int,\
		PRIMARY KEY(`id`))";

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

  // 2 清空表 truncate t_data
  sql = "truncate t_data";
  re = mysql_query(&mysql, sql.c_str());
  if (re != 0) {
    std::cerr << mysql_error(&mysql) << std::endl;
  }

  // 3 初始化stmt mysql_stmt_init
  MYSQL_STMT *stmt = mysql_stmt_init(&mysql);
  if (!stmt) {
    std::cerr << "mysql_stmt_init failed!" << mysql_error(&mysql) << std::endl;
  }

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

  // 5 打开并读取文件
  std::string filename = "mysql.jpg";

  //读取二进制
  std::fstream in(filename, std::ios::in | std::ios::binary);
  if (!in.is_open()) {
    std::cerr << "file " << filename << " open failed!" << std::endl;
    return 1;
  }
  //文件指针移动到结尾处
  in.seekg(0, std::ios::end);
  //文件大小和文件二进制地址
  unsigned int filesize = in.tellg();
  //回到开头
  in.seekg(0, std::ios::beg);

  char *data = new char[filesize];
  unsigned 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;  // data 文件二进制内容
  bind[1].buffer = data;                  //二进制文件
  bind[1].buffer_length = filesize;

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

  if (mysql_stmt_bind_param(stmt, bind) != 0) {
    std::cerr << "mysql_stmt_bind_param failed! " << mysql_stmt_error(stmt)
              << std::endl;
  }

  // 7 执行stmt sql
  if (mysql_stmt_execute(stmt) != 0) {
    std::cerr << "mysql_stmt_execute failed! " << mysql_stmt_error(stmt)
              << std::endl;
  }
  delete[] data;
  mysql_stmt_close(stmt);

  // 8 查询二进制数据,并保存问文件
  sql = "select * from t_data";
  re = mysql_query(&mysql, sql.c_str());
  if (re != 0) {
    std::cerr << "mysql query failed!" << mysql_error(&mysql) << std::endl;
  }
  //获取结果集
  MYSQL_RES *res = mysql_store_result(&mysql);
  if (!res) {
    std::cerr << "mysql_store_result failed!" << mysql_error(&mysql)
              << std::endl;
  }
  //取一行数据
  MYSQL_ROW row = mysql_fetch_row(res);
  if (!row) {
    std::cerr << "mysql_fetch_row failed!" << mysql_error(&mysql) << std::endl;
  }
  std::cout << row[0] << " " << row[1] << " " << row[3] << std::endl;

  //获取每列数据的大小
  unsigned long *lens = mysql_fetch_lengths(res);
  int fnum = mysql_num_fields(res);
  for (int i = 0; i < fnum; i++) {
    std::cout << "[" << lens[i] << "]";
  }
  filename = "img_out_";
  filename += row[1];
  std::fstream out(filename, std::ios::out | std::ios::binary);
  if (!out.is_open()) {
    std::cerr << "open file  " << filename << " failed!" << std::endl;
  }
  out.write(row[2], lens[2]);
  out.close();

  mysql_close(&mysql);
  mysql_library_end();
}

创建存储过程

// mysqltest.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include "mysql.h"
#include <iostream>
#include <thread>
#include <chrono>
#include <sstream>
#include <map>
#include <fstream>

int main()
{
  //初始化mysql上下文
  MYSQL mysql;
  //单线程模式 mysql_init自动调用 mysql_library_init 线程不安全
  mysql_init(&mysql);
  const char *host = "127.0.0.1";
  const char *user = "root";
  const char *pass = "root";
  const char *db = "cpptest";  //数据库名称

  if (!mysql_real_connect(&mysql, host, user, pass, db, 3306, 0,
                          CLIENT_MULTI_STATEMENTS))
  {
    std::cout << "mysql connect failed!" << mysql_error(&mysql) << std::endl;
  } else {
    std::cout << "mysql connect success!" << std::endl;
  }

  std::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) {
    std::cout << mysql_error(&mysql) << std::endl;
  }
  // 2 定义变量并复制
  std::cout << "IN in=1 out=2 inout=3" << std::endl;
  sql = "SET @A=1;SET @B=2;SET @C=3;";
  re = mysql_query(&mysql, sql.c_str());
  if (re != 0) {
    std::cout << mysql_error(&mysql) << std::endl;
  }
  do {
    std::cout << "SET affect " << mysql_affected_rows(&mysql) << std::endl;
  }
  // 0 还有结果, -1 没有结果 >1错误
  while (mysql_next_result(&mysql) == 0);

  // 3 调用存储过程 call
  sql = "call p_test(@A,@B,@C)";
  re = mysql_query(&mysql, sql.c_str());
  if (re != 0) {
    std::cout << mysql_error(&mysql) << std::endl;
  }
  std::cout << "In Proc:";
  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]) {
          std::cout << row[i] << " ";
        } else
          std::cout << "NULL"
               << " ";
      }
      std::cout << std::endl;
    }
    mysql_free_result(res);
  }
  // 0 还有结果, -1 没有结果 >1错误
  while (mysql_next_result(&mysql) == 0);

  // 4 获取存储过程的结果
  sql = "select @A,@B,@C";
  re = mysql_query(&mysql, sql.c_str());
  if (re != 0) {
    std::cout << mysql_error(&mysql) << std::endl;
  }
  MYSQL_RES *res = mysql_store_result(&mysql);
  std::cout << "out: ";
  MYSQL_ROW row = mysql_fetch_row(res);
  std::cout << " in=" << row[0];
  std::cout << " out=" << row[1];
  std::cout << " inout=" << row[2];
  mysql_free_result(res);
  std::cout << std::endl;

  mysql_close(&mysql);
  mysql_library_end();
}

  • 结果:

  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值