【MySQL】11.使用 C 语言访问 MySQL

使用C语言访问MySQL

  • 一.检查第三方库是否配置成功
  • 二.MySQL 常用接口
    • 1.创建,销毁操作句柄
    • 2.使用句柄连接数据库
    • 3.向 mysqld 发送指令
    • 4.查询相关函数
  • 三.使用示例

一.检查第三方库是否配置成功

想要使用代码连接数据库,必须使用 MySQL 官方提供的第三方库。早在我们第一节使用 yum 安装 MySQL 的时候,
就安装了三个东西:MySQL 客户端,MySQL 服务端,MySQL 开发包(库)。所以我们只需检查一下环境是否就绪。

//1.检查是否有MySQL库
[liuyi@centos-7 usr]$ ls /usr/lib64/mysql/
libmysqlclient.a        libmysqlclient_r.so.18.1.0  libmysqlclient.so.18      libmysqlclient.so.20       libmysqlservices.a  plugin
libmysqlclient_r.so.18  libmysqlclient.so           libmysqlclient.so.18.1.0  libmysqlclient.so.20.3.31  mecab

//2.检查是否有MySQL头文件
[liuyi@centos-7 usr]$ ls /usr/include/mysql/
big_endian.h              keycache.h       my_command.h        my_getopt.h         mysqld_ername.h  mysqlx_ername.h    my_xml.h                    plugin_validate_password.h  thr_cond.h
binary_log_types.h        little_endian.h  my_compiler.h       my_global.h         mysqld_error.h   mysqlx_error.h     plugin_audit.h              sql_common.h                thr_mutex.h
byte_order_generic.h      m_ctype.h        my_config.h         my_list.h           mysql_embed.h    mysqlx_version.h   plugin_ftparser.h           sql_state.h                 thr_rwlock.h
byte_order_generic_x86.h  m_string.h       my_config_x86_64.h  mysql               mysql.h          my_sys.h           plugin_group_replication.h  sslopt-case.h               typelib.h
decimal.h                 my_alloc.h       my_dbug.h           mysql_com.h         mysql_time.h     my_thread.h        plugin.h                    sslopt-longopts.h
errmsg.h                  my_byteorder.h   my_dir.h            mysql_com_server.h  mysql_version.h  my_thread_local.h  plugin_keyring.h            sslopt-vars.h
如果以上东西没有,则执行以下命令安装开发包:
sudo yum install -y mysql-devel
#include <mysql/mysql.h>
#include <iostream>
using namespace std;

int main()
{
    cout << "mysql client version: " << mysql_get_client_info() << endl;
    return 0;
}

//编译命令如下:
//g++ -o test test.cc -std=c++11 -L /usr/lib64/mysql -l mysqlclient
//如果编译成功,则说明环境没有问题
[liuyi@centos-7 test_db]$ ./test 
mysql client version: 5.7.44

二.MySQL 常用接口

MySQL 官方文档

1.创建,销毁操作句柄

MYSQL* mysql_init(MYSQL* mysql);
功能:创建一个mysql对象,这就是我们操作的句柄
返回值:如果返回NULL则创建失败,否则返回一个创建出的对象

void mysql_close(MYSQL* mysql);
功能:销毁mysql对象

2.使用句柄连接数据库

MYSQL* mysql_real_connect(MYSQL *mysql, //句柄
                   const char *host,    //mysqld所在主机
                   const char *user,    //mysql用户名
                   const char *passwd,  //登录密码
                   const char *db,      //数据库名
                   unsigned int port,   //mysqld所在端口
                   const char *unix_socket,   //一般设为nullptr
                   unsigned long client_flag) //一般设为0
                   
功能:连接数据库
返回值:连接失败返回nullptr,连接成功返回句柄本身

3.向 mysqld 发送指令

int mysql_query(MYSQL *mysql,
            const char *stmt_str)
功能:向mysqld发送指令执行
返回值:0表示语句执行成功,非0表示执行失败    

int mysql_set_character_set(MYSQL *mysql,
                        const char *csname)    
功能:设置当前连接的字符串编码格式,必须让它和mysqld的编码格式保持一致,否则中文会乱码     
返回值:为0则设置成功

4.查询相关函数

select查询到的数据会保存在MYSQL对象中

MYSQL_RES* mysql_store_result(MYSQL *mysql);
功能:将保存在MySQL对象中的数据进行整合,把查询结果保存到MYSQL_RES对象中
返回值:为nullptr表示失败
说明:
MYSQL_RES也是第三方库定义的一个结构体类型,其内部维护了一个char**的数组,
以后处理select结果会频繁用到该对象;
mysql_store_result内部肯定会malloc一段空间用于保存结果,最后一定要调用相应函数释放以免内存泄露

unsigned int mysql_num_rows(MYSQL_RES *res); 
功能:返回表的行数(不包含字段行)
unsigned int mysql_num_fields(MYSQL_RES *res);
功能:返回表的列数(不包含字段行)

MYSQL_ROW mysql_fetch_row(MYSQL_RES *result); 
功能:获取一行的结果,每次调用后会自动迭代
返回值:为nullptr表示获取失败
说明:MYSQL_ROW是对char**typedef

MYSQL_FIELD *mysql_fetch_fields(MYSQL_RES *res);
功能:返回该表的所有字段的详细信息
返回值:为nullptr表示获取失败
说明:MYSQL_FIELD是一个结构体类型,包含一个字段的详细信息,如字段名,属性,所属表的名称等

void mysql_free_result(MYSQL_RES* res)
功能:释放mysql_store_result中申请的空间,释放后就不要试图访问res了

在这里插入图片描述

三.使用示例

#include <mysql/mysql.h>
#include <iostream>
#include <cassert>

const char *host = "127.0.0.1"; //写localhost也行
const char *user = "ly";
const char *password = "**********"; //密码不方便透露
const char *db = "test_db";
unsigned int port = 3306;
using namespace std;

int main()
{
    //1.创建句柄
    MYSQL *mysql = mysql_init(nullptr);
    if (mysql == nullptr)
    {
        cout << "创建MySQL对象失败" << endl;
        return 1;
    }

    //2.连接数据库并修改本次连接中客户端的编码方式
    assert(mysql_real_connect(mysql, host, user, password, db, port, nullptr, 0) != nullptr);
    mysql_set_character_set(mysql, "utf8");
    
    //3.执行建表,插入,查询语句
    assert(mysql_query(mysql, "create table test_tb(id int, name varchar(20))") == 0);
    assert(mysql_query(mysql, "insert into test_tb values(1, '张三')") == 0);
    assert(mysql_query(mysql, "insert into test_tb values(2, '李四')") == 0);
    assert(mysql_query(mysql, "select * from test_tb") == 0);
    
    //4.将查询结果保存到res中
    MYSQL_RES *res = mysql_store_result(mysql);

    //5.处理查询结果
    int rows = mysql_num_rows(res);
    int cols = mysql_num_fields(res);

    MYSQL_FIELD *fields_array = mysql_fetch_fields(res);
    for (int i = 0; i < cols; i++)
    {
        cout << fields_array[i].name << "\t";
    }
    cout << endl;
    for (int i = 0; i < rows; i++)
    {
        char **line = mysql_fetch_row(res);
        for (int j = 0; j < cols; j++)
        {
            cout << line[j] << "\t";
        }
        cout << endl;
    }

    //6.释放查询结果
    mysql_free_result(res);

    //7.销毁句柄
    mysql_close(mysql);
    return 0;
}

//编译运行结果:
[liuyi@centos-7 test_db]$ ./test 
id      name
1       张三
2       李四
上一篇:集合的不可变性:深入理解Java中的不可变集合


下一篇:快手开源LivePortrait,实现表情姿态极速迁移,GitHub 6.5K Star