【MySQL系列】使用C语言连接MySQL

2023-09-14 09:57:30

「前言」文章内容大致是使用C语言连接MySQL。

「归属专栏」MySQL

「主页链接」个人主页

「笔者」枫叶先生(fy)

MySQL

一、Connector/C使用

按照前面MySQL的安装流程,安装完MySQL,MySQL相应的连接相关的库也被下载下来了
查看动态库是否存在

ls /lib64/mysql/

在这里插入图片描述
查看MySQL相应的头文件是否存在

ls /usr/include/mysql

在这里插入图片描述
如果不存在,需要安装一下

 yum install -y mysql-devel

在这里插入图片描述
下面先通过调用mysql_get_client_info来判断库是否引入成功,该函数的作用就是获取客户端的版本信息

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

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

进行编译

g++ -o mysql mysql.cpp -L/lib64/mysql -lmysqlclient
  • -L:用于指定库文件的搜索路径
  • -l:用于指明需要连接库文件路径下的哪一个库(L的小写)

这些在动静态库那里都讲过了,不再解释

运行可执行程序后,可以看到客户端的版本号
在这里插入图片描述

至此库已经成功被引入,接下来就是库函数的使用了

二、MySQL的C接口介绍

2.1 连接MySQL

1、初始化

在连接数据库之前,需要先创建一个MySQL对象,进行初始化

该函数如下:

MYSQL* mysql_init(MYSQL *mysql);

说明:

  • 该函数用来分配或者初始化一个MySQL对象
  • 如果传入参数为NULL,mysql_init将自动分配一个MYSQL对象(句柄)并返回
  • 如果传入的是一个MYSQL对象,该函数会对该对象进行初始化

MYSQL是一个结构体,定义如下:
在这里插入图片描述
在这里插入图片描述

2、连接数据库

初始化完毕之后,必须先链接数据库,才能进行后续操作(mysql网络部分是基于TCP/IP的)

连接数据库的函数如下:

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 clientflag);

参数说明:

  • mysql:表示在连接数据库前,调用mysql_init函数创建的MYSQL对象
  • host:表示需要连接的MySQL服务器的IP地址,"127.0.0.1"表示连接本地MySQL服务器
  • user:表示连接MySQL服务器时,登录所使用的用户名
  • passwd:表示连接MySQL服务器时,登录所使用用户的密码
  • db:表示连接MySQL服务器后,需要使用的是哪一个数据库
  • port:表示连接的MySQL服务器,所对应的端口号
  • unix_socket:表示连接时应该使用的套接字或命名管道,通常设置为NULL
  • clientflag:可以设置为多个标志位的组合,表示允许特定的功能,通常设置为0

返回值

  • 如果连接数据库成功,则返回一个MYSQL对象(句柄),该对象与第一个参数mysql相同
  • 如果连接数据库失败,则返回NULL

3、关闭数据库连接

与数据库交互完毕后,需要关闭数据库连接

关闭数据库连接的函数如下:

void mysql_close(MYSQL *sock);

说明:

  • 参数sock,就是连接数据库前调用mysql_init创建的MySQL对象,传入该对象即可

连接测试

代码如下:

#include <iostream>
#include <string>
#include <mysql/mysql.h>
using namespace std;

const string host = "127.0.0.1";
const string user = "fengye";
const string password = "123123aa";
const string db = "test_db";
const int port = 3306;

int main()
{
    // 1.初始化
    MYSQL* my = mysql_init(nullptr);
    // 2.连接数据库
    if(mysql_real_connect(my, host.c_str(), user.c_str(), password.c_str(), db.c_str(), port, nullptr, 0) == nullptr)
    {
        cerr << "数据库连接失败!" << endl;
        return 1;
    }
    cout << "连接成功" << endl;
    // 3.关闭连接
    mysql_close(my);
    
    return 0;
}

进行编译运行,数据库连接成功
在这里插入图片描述

2.2 发送SQL请求

数据库连接成功了,就可以进行进行发送SQL请求了

设置编码格式

在连接数据库之后,需要统一客户端和服务器的编码格式,避免在数据交互过程中出现乱码,设置编码格式的函数如下:

int mysql_set_character_set(MYSQL *mysql, const char *csname);

说明:

  • 参数mysql:是mysql_init函数创建初始化的MYSQL对象
  • csname:表示要设置的编码格式,如"utf8"

返回值:为0表示设置成功,否则表示设置失败

注:设置链接原始默认字符集是latin1

发送SQL请求

下发SQL请求的函数如下:

int	mysql_query(MYSQL *mysql, const char *q);

说明:

  • mysql:是mysql_init函数创建初始化的MYSQL对象
  • q: 表示向MySQL服务器下发的SQL请求,SQL最后可以不带分号,也可以带

返回值:为0表示SQL执行成功,否则表示SQL执行失败

向数据库中插入数据

#include <iostream>
#include <string>
#include <mysql/mysql.h>
using namespace std;

const string host = "127.0.0.1";
const string user = "fengye";
const string password = "123123aa";
const string db = "test_db";
const int port = 3306;

int main()
{
    // 1.初始化
    MYSQL* my = mysql_init(nullptr);
    // 2.连接数据库
    if(mysql_real_connect(my, host.c_str(), user.c_str(), password.c_str(), db.c_str(), port, nullptr, 0) == nullptr)
    {
        cerr << "数据库连接失败!" << endl;
        return 1;
    }
    cout << "连接成功" << endl;

    // 设置编码格式
    mysql_set_character_set(my, "utf8");

    string sql = "insert into user (name, age) values ('王五', 19);";
    if(mysql_query(my, sql.c_str()) != 0)
    {
        cerr << sql << " failed." << endl;
        return 2;
    }
    cout << sql << " sucsess." << endl;
    // 3.关闭连接
    mysql_close(my);
    
    return 0;
}

编译运行
在这里插入图片描述

删除数据库中的数据

进行删除数据测试
在这里插入图片描述
编译运行
在这里插入图片描述

修改数据库中的数据

进行修改数据库数据测试
在这里插入图片描述
编译运行
在这里插入图片描述

2.3 获取结果集

  • 对数据库中的数据进行增删改操作时,都只需要调用mysql_query向服务器下发对应的SQL请求,即不需要返回结果
  • 对于数据库中的数据进行查询操作时,除了需要调用mysql_query向服务器下发对应的查询SQL,还需要获取查询结果,把MySQL服务器查到的数据获取过来

获取查询结果的函数如下:

MYSQL_RES* mysql_store_result(MYSQL *mysql);

注:

  • 获取到的查询结果保存到MYSQL_RES变量中
  • 该函数malloc了一片内存空间来存储查询过来的数据,需要进行释放该空间,否则会造成内存泄漏

MYSQL_RES是一个结构体,定义如下:
在这里插入图片描述
释放结果集函数:

void mysql_free_result(MYSQL_RES *result);

说明:参数传入结果集即可

获取结果集成功后,需要获取结果集的行数和列数,方便进行遍历数据

获取查询结果的行数

获取查询结果的行数的函数如下:

my_ulonglong mysql_num_rows(MYSQL_RES *res);

获取查询结果的列数

获取查询结果的列数的函数如下:

unsigned int mysql_num_fields(MYSQL_RES *res);

获取查询结果中的一行数据

MYSQL_ROW mysql_fetch_row(MYSQL_RES *result);

注:

  • 该函数将会从指定的MYSQL_RES对象中,获取查询结果中的一行数据

获取列名

获取查询结果的列属性的函数如下:

MYSQL_FIELD* mysql_fetch_fields(MYSQL_RES *res);

注:

  • 列属性也是需要进行特定获取的
  • 每个MYSQL_FIELD对象中保存着对应列的各种列属性
  • 我们需要获取列名称,即name

MYSQL_FIELD结构体定义如下:
在这里插入图片描述

遍历结果集类似于遍历二维数组

查询演示

#include <iostream>
#include <string>
#include <mysql/mysql.h>
using namespace std;

const string host = "127.0.0.1";
const string user = "fengye";
const string password = "123123aa";
const string db = "test_db";
const int port = 3306;

int main()
{
    // 1.初始化
    MYSQL* my = mysql_init(nullptr);
    // 2.连接数据库
    if(mysql_real_connect(my, host.c_str(), user.c_str(), password.c_str(), db.c_str(), port, nullptr, 0) == nullptr)
    {
        cerr << "数据库连接失败!" << endl;
        return 1;
    }
    cout << "连接成功" << endl;

    // 设置编码格式
    mysql_set_character_set(my, "utf8");

    // string sql = "insert into user (name, age) values ('王五', 19);";
    // string sql = "delete from user where id=4";
    // string sql = "update user set age=66 where id=1";
    string sql = "select * from user";
    if(mysql_query(my, sql.c_str()) != 0)
    {
        cerr << sql << " failed." << endl;
        return 2;
    }
    cout << sql << " sucsess." << endl;

    // 获取结果集
    MYSQL_RES* res = mysql_store_result(my);
    int row = mysql_num_rows(res);   // 数据行数
    int col = mysql_num_fields(res); // 数据列数
    
    // 获取每列的属性,并打印
    MYSQL_FIELD* fields = mysql_fetch_field(res);
    for(int i = 0; i < col; ++i)
    {
        cout << fields[i].name << "\t";
    }
    cout << endl;

    // 遍历数据
    for(int i = 0; i < row; ++i)
    {
        // 获取每一行
        MYSQL_ROW rows = mysql_fetch_row(res);
        for(int j = 0; j < col; ++j)
        {
            cout << rows[j] << "\t";
        }
        cout << endl;
    }

    // 释放res
    mysql_free_result(res);

    // 3.关闭连接
    mysql_close(my);
    
    return 0;
}

编译运行,数据成功被获取出来
在这里插入图片描述

  • 再说一下结果集,结果集指向一个数组,数组里面存放的都是char**的指针
  • 使用mysql_fetch_row函数获取一行,返回的结果实际是char**,char**又指向一个char*的数组
    在这里插入图片描述
    --------------------- END ----------------------
「 作者 」 枫叶先生
「 更新 」 2023.9.14
「 声明 」 余之才疏学浅,故所撰文疏漏难免,
          或有谬误或不准确之处,敬请读者批评指正。
更多推荐

2023年云南省职业院校技能大赛中职组“网络安全”赛项样题

2023年云南省职业院校技能大赛中职组“网络安全”赛项样题一、竞赛时间总计:180分钟二、竞赛阶段竞赛阶段任务阶段竞赛任务竞赛时间分值A、B模块A-1登录安全加固180分钟200分A-2数据库加固A-3服务加固SSH\VSFTPDA-4防火墙策略B-1隐写术应用-B400分B-2内存取证B-3数据库渗透B-4Linux

信息检索与数据挖掘 | (二)布尔检索与倒排索引

文章目录📚词项-文档关联矩阵🐇相关名词🐇词项-文档关联矩阵的布尔查询处理📚倒排索引🐇关于索引🐇建立索引🐇基于倒排索引的布尔查询处理🐇查询优化📚字典数据结构🐇哈希表🐇各种树🐇B树vsB+树📚短语查询及含位置信息的倒排记录🐇二元词索引(Biwordindexes)🐇位置信息索引🐇混合索引机制

Hadoop学习总结(搭建Hadoop集群的安装准备)

目录一、安装jdk1、查看电脑中安装的jdk版本2、安装jdk173、配置path(配置jdk)4、对jdk8和jdk17版本做自由切换二、安装vmware三、安装centos7(虚拟机)四、虚拟机设置五、虚拟机网络配置1、查看NAT的网段2、修改主机名(1)修改虚拟机的hosts(2)修改虚拟机的hostname3、

Spring MVC 中的数据绑定和验证机制是什么,如何使用

在SpringMVC应用中,数据绑定和验证是非常重要的一部分,它们可以帮助我们将用户提交的数据绑定到Java对象上,并对数据进行验证,保证数据的正确性和可靠性。在SpringMVC中,数据绑定和验证机制都是通过注解来实现的。本文将介绍SpringMVC中的数据绑定和验证机制,以及如何使用它们。数据绑定数据绑定是将用户提

SSM整合(细节拉满)|将Mybatis、Spring、SpringMVC三个框架整合起来,通过一个demo来练习

环境要求环境:IDEAMySQL5.7.19Tomcat9Maven3.6要求:需要熟练掌握MySQL数据库,Spring,JavaWeb及MyBatis知识,简单的前端知识;数据库环境创建一个存放书籍数据的数据库表,并插入一些示例数据SSM整合新建一个空的Maven项目导入相关依赖将数据库与IDEA连接起来把项目结构

解决Spring Boot 2.7.16 在服务器显示启动成功无法访问问题:从本地到服务器的部署坑

🌷🍁博主猫头虎带您GotoNewWorld.✨🍁🦄博客首页——猫头虎的博客🎐🐳《面试题大全专栏》文章图文并茂🦕生动形象🦖简单易学!欢迎大家来踩踩~🌺🌊《IDEA开发秘籍专栏》学会IDEA常用操作,工作效率翻倍~💐🌊《100天精通Golang(基础入门篇)》学会Golang语言,畅玩云原生,走遍大

如何高效管理多个 Outlook 邮箱?

在我们日常工作和生活中,使用多个Outlook邮箱可以带来一定的便利和灵活性。本文将介绍多个Outlook邮箱的用途,以及如何注册多个Outlook邮箱并确保它们之间不关联。最后,我们将讨论管理多个Outlook邮箱所面临的困难,并介绍一个解决方案——VMLogin浏览器,可以高效管理多个账号并防止关联问题。一、多个O

RocketMQ 发送事务消息

文章目录事务的相关理论事务ACID特性CAP理论BASE理论事务消息应用场景MQ事务消息处理处理逻辑RocketMQ事务消息处理流程官网事务消息流程图rocketmq-client-java示例(gRPC协议)创建事务主题生产者消费者rocketmq-client示例(Remoting协议)生产者消费者事务的相关理论事

初识ElasticSearch

文章目录初识ElasticSearch前言1、初识ElasticSearch1.1ES概述1.2倒排索引1.3ES中的一些常见概念1.4安装ES和Kibana2、索引库操作2.1Mapping映射属性2.2索引库的CRUD2.2.1创建索引和映射2.2.2查询索引库2.2.3修改索引库2.2.4删除索引库3、文档操作3

走近ChatGPT与类似产品:原理解析与比较

目录1.引言1.1技术的进步与自然语言处理1.2ChatGPT的崭新概念2.ChatGPT:一览众山小2.1GPT-3.5架构简介2.2ChatGPT的学习与训练2.3文本生成的工作原理3.市场上类似产品调研3.1对话式人工智能产品分类3.2文心一言3.3讯飞星火4.应用前景与局限性展望4.1ChatGPT的未来应用场

【学习笔记】多模态综述

多模态综述前言1.CLIP&ViLT2.ALBEF3.VLMO4.BLIP5.CoCa6.BeiTv3总结参考链接前言本篇学习笔记虽然是多模态综述,本质上是对ViLT后多模态模型的总结,时间线为2021年至2022年,在这两年,多模态领域的模型也是卷的飞起,不断刷新领域的SOTA。在模型结构和数据上提出了很多高效有用的

热文推荐