文章目录

  • ​​1.工程配置​​
  • ​​2.MySql C API​​

1.工程配置

  • 包含头文件
mysql.h
  • 导入库libmysql.lib
#include <mysql.h>这么写的话,需要将mysql server的include路径放在vs中下面位置,否则无法找到

(P122)mysql数据库(十四):工程配置,MySql C API_#include


MySQL_conn\MySQL_conn.vcproj文件所在的位置是工程文件目录;

或者把该include的目录拷贝到\MySQL_conn\include这里,那么vs工程配置的路径需要修改成如下:

(P122)mysql数据库(十四):工程配置,MySql C API_MySQL_02

  • libmysql.lib和libmysql.dll的区别
    (1)libmysql.lib这仅仅只是包含libmysql.dll的一些符号信息,并不包含实际的实现代码;
    libmysql.dll这包含实际的实现代码,比比大小,dll也比较大;
    (2)动态链接库的使用:一种是静态链接(动态链接库在链接的时候并没有把dll中的代码链接到可执行文件中,仅仅把符号信息lib的内容链接到可执行文件中,这种方式其实是对动态链接库的静态链接 ),一种是动态链接(使用LoadLibrary来进行动态链接,GetProcAddress获取动态链接库中某个函数,然后去调用它即可)。

    libmysql.lib在vs中的配置如下

    libmysql.lib的位置

    生成的可执行文件在运行的时候需要在debug目录下寻找libmysql.dll文件,所以需要将其放到MySQL_conn\Debug\libmysql.dll目录下或者MySQL_conn目录下也可以。

2.MySql C API

  • 常用的API如下:
(1)MYSQL结构代表一个连接句柄
MYSQL *mysql_init(MYSQL *mysql) ;
如果mysql是NULL指针,该函数将分配、初始化、并返回新对象。否则,将初始化对象,并返回对象的地址。如果mysql_init()分配了新的对象,当调用mysql_close()来关闭连接时。将释放该对象。

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)

(2)mysql_real_connect
my_bool reconnect = true;
mysql_options(mysql, MYSQL_OPT_RECONNECT, &reconnect);
mysql_options(mysql, MYSQL_SET_CHARSET_NAME, "gbk");

(3)mysql_query
int mysql_query(MYSQL *mysql, const char *query)
mysql_affected_rows
mysql_store_result
mysql_num_fields
mysql_num_rows
mysql_fetch_field
mysql_fetch_row
mysql_free_result
  • 参考:MySQL 5.1参考手册中25.2 MySql C API
MYSQL 
该结构代表1个数据库连接的句柄。几乎所有的MySQL函数均使用它。不应尝试拷贝MYSQL结构。不保证这类拷贝结果会有用。

MYSQL_RES
该结构代表返回行的查询结果(SELECT, SHOW, DESCRIBE, EXPLAIN)。在本节的剩余部分,将查询返回的信息称为“结果集”。

MYSQL_ROW
这是1行数据的“类型安全”表示。

MYSQL_FIELD
代表一个字段

scott数据库,里面有emp员工表

(P122)mysql数据库(十四):工程配置,MySql C API_#include_03

  • eg:P122\MySQL_conn\main.cpp,P122\Debug\libmysql.dll,P122\include,P122\lib
#include <Windows.h>
#include <mysql.h>
#include <stdio.h>

int main(void)
{

//下面的方法仅仅初始化conn对象,内部并不会分配MYSQL对象
// MYSQL conn;
// mysql_init(&conn);
// mysql_close(&conn));close时并不释放conn对象,因为conn对象是栈上的变量

// 初始化一个连接句柄MYSQL
MYSQL* mysql;
mysql = mysql_init(NULL);//如果参数是NULL,则内部会分配一个MYSQL对象,即动态创建了一块内存
if (mysql == NULL)
{
printf("error: %s\n", mysql_error(mysql));
return 1;
}

//设置连接选项
//my_bool实际上是char类型
my_bool reconnect = true;
mysql_options(mysql, MYSQL_OPT_RECONNECT, &reconnect);//重连选项
mysql_options(mysql, MYSQL_SET_CHARSET_NAME, "gbk");//采用的字符集gdb,可以使用中文

//连接数据库
/*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连接句柄;
DB的主机名称;
用户名;
密码;
要连接的数据库;
端口号,填写0则使用默认端口号3306;
unix域套接字名称或者命名管道的名称(windows只有命名管道的名称),通常填写NULL;
通常填写0即可;
*/

//localhost表示本机
if (!mysql_real_connect(mysql, "localhost", "root", "123456", "scott",
0, NULL, 0))
{
printf("error: %s\n", mysql_error(mysql));
return 1;
}

int result;

//没有返回结果集的操作
// sql操作的insert,update,delete没有返回结果集的操作,但是会改变数据库的状态
//执行查询语句,插入一条记录
result = mysql_query(mysql, "insert into emp values(8888, 'YYYY', 'CLERK', 7782, '1982-01-23', 1300, null, 30)");
if (result != 0)
{
printf("error: %s\n", mysql_error(mysql));
return 1;
}

//由于没有返回结果集的操作,所以通过mysql_affected_rows函数来判断影响了多少行
printf("%llu 行受影响\n", mysql_affected_rows(mysql));//mysql_affected_rows返回值是ulonglong,所以用llu打印

// 有返回结果集的操作
//查询操作
result = mysql_query(mysql, "select * from emp where deptno=30;");
if (result != 0)
{
printf("error: %s\n", mysql_error(mysql));
return 1;
}

//对于有返回结果集的操作,取出结果集mysql_res
MYSQL_RES* mysql_res;
MYSQL_FIELD* mysql_field;
MYSQL_ROW mysql_row;//类型其实是char**
unsigned int cols;
mysql_res = mysql_store_result(mysql);//取出结果集mysql_res
cols = mysql_num_fields(mysql_res);//mysql_num_fields表示字段的个数,即列数
if (mysql_res)
{
printf("返回%llu行\n", mysql_num_rows(mysql_res));//行数

while ((mysql_field = mysql_fetch_field(mysql_res)))//获取每个字段的名称
{
printf("%s\t", mysql_field->name);
}
printf("\n");

while ((mysql_row = mysql_fetch_row(mysql_res)))//一行一行获取,行里面有多个列
{
//因为有的字段可能是NULL,所以不能通过空指针来判断,只能通过列的个数来判断
for (unsigned int i=0; i<cols; ++i)
{
printf("%s\t", mysql_row[i] ? mysql_row[i] : "NULL");
}
printf("\n");
}
mysql_free_result(mysql_res);
}


mysql_close(mysql);
return 0;
}
  • 测试:
    可以在navicat中直接删除表的一条记录
  • (P122)mysql数据库(十四):工程配置,MySql C API_#include_04

  • 下面的表中sal为空的话,就是一个NULL,空指针
  • (P122)mysql数据库(十四):工程配置,MySql C API_mysql_05

  • eg:P122\BankServer\main.cpp,P122\BankServer\DAL\MysqlDB.h,P122\BankServer\DAL\MysqlDB.cpp,P122\Inc,P122\Lib,P122\Bin
    将Mysql C API封装成类来使用
#include "Server.h"
#include "../Public/MD5.h"

#include "DAL/MysqlDB.h"
#include "../Public/Exception.h"
#include "../Public/Logging.h"

#include <stdio.h>
#include <iostream>
using namespace std;

using namespace PUBLIC;
using namespace DAL;

int main(void)
{
//MD5 md5;

//unsigned char hash[16];
//md5.MD5Make(hash, (unsigned char const *)"cppcourse", 9);
//int i;
//for (i=0; i<16; ++i)
//{
// printf("%0X", hash[i]);
//}

//printf("\n");

MysqlDB db;
try
{
db.Open("localhost", "root", "123456", "scott", 0);

//主要执行的就是:updat.insert,delete操作
unsigned long long ret = db.ExecSQL(
"insert into emp values(8888, 'YYYY', 'CLERK', 7782, '1982-01-23', 1300, null, 30)");
cout<<ret<<"行受影响"<<endl;

//查询操作,QuerySQL指的就是select语句
MysqlRecordset rs = db.QuerySQL("select * from emp where deptno=30;");
cout<<"empno ename"<<endl;
for (unsigned int i=0; i<rs.GetRows(); ++i)
{
cout<<rs.GetItem(i, "empno")<<" "<<rs.GetItem(i, "ename")<<endl;
}
}
catch (Exception& e)
{
LOG_INFO<<e.what();
db.Close();
}

//执行完毕,别忘记关闭
db.Close();
return Singleton<Server>::Instance().Start();
}
  • ABCBank调用mysql需要注意的地方
    第三方的头文件位置:ABCBank\Inc
    第三方的lib文件位置:ABCBank\Lib
    第三方的dll文件位置:ABCBank\Bin\libmysql.dll
    工程配置:
  • (P122)mysql数据库(十四):工程配置,MySql C API_mysql_06


  • (P122)mysql数据库(十四):工程配置,MySql C API_MySQL_07

    (P122)mysql数据库(十四):工程配置,MySql C API_#include_08

  • 测试:
  • (P122)mysql数据库(十四):工程配置,MySql C API_mysql_09