C语言连接【MySQL】

news2024/11/16 9:52:48

稍等更新图片。。。。

文章目录

  • 安装 MySQL 库
  • 连接 MySQL
    • MYSQL 类
    • 创建 MySQL 对象
    • 连接数据库
    • 关闭数据库连接
    • 示例
  • 发送命令
  • 设置编码格式
  • 插入、删除或修改记录
  • 查询记录
    • 示例
  • 参考资料

安装 MySQL 库

在 CentOS7 下,使用命令安装 MySQL:

yum install mysql-devel

/usr/include可以看到一个mysql新目录,里面存放的是 mysql 的头文件。另外在 /lib64/mysql/ 以及 /usr/lib64/mysql 目录下存放了 mysql 的动态和静态库。

用一个 MySQL 库提供的接口验证 MySQL 库是否安装成功:

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

using namespace std;

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

编译:

g++ sql.cc -o sql -I/usr/include/mysql -L/usr/lib64/mysql -lmysqlclient
image-20240227182356233

编译选项中关于库的使用:

  • -I:用于指明头文件的搜索路径。
  • -L:用于指明库文件的搜索路径。
  • -l:用于指明需要连接库文件路径下的哪一个库。
image-20240227182921177

因为这个库没有在链接的默认目录/usr/lib64下,所以作为第三方导入的库,在编译时需要显式地指定-L/usr/lib64/mysql;同理,头文件不在默认目录/usr/include下,所以要显式地指定-I/usr/include/mysql。在这个目录下,存在名为mysqlclient的第三方库,同样需要用-l显式地声明。

只要正常运行上面的程序,那就表明库的链接没有问题,剩下的就是简单的 API 使用。

连接 MySQL

MYSQL 类

在使用 MySQL 提供的接口之前,需要了解一下这个重要的类。

MYSQL类是一个非常核心的结构体,它用于表示与 MySQL 服务器的一个连接实例。在客户端程序中,这个结构体用来保存客户端与数据库服务器之间连接的所有必要信息,包括但不限于:

  • 服务器的地址
  • 用户名和密码
  • 正在使用的数据库
  • 网络连接的状态和配置
  • 错误信息和错误码
  • 查询结果
  • 选项设置

mysql.h中可以查看 MYSQL 结构体的定义(了解即可):

typedef struct st_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_st *charset;
  MYSQL_FIELD	*fields;
  MEM_ROOT	field_alloc;
  my_ulonglong affected_rows;
  my_ulonglong insert_id;		/* id if insert on table with NEXTNR */
  my_ulonglong 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;
  my_bool	free_me;		/* If free in mysql_close */
  my_bool	reconnect;		/* set to 1 if automatic reconnect */

  /* session-wide random string */
  char	        scramble[SCRAMBLE_LENGTH+1];
  my_bool unused1;
  void *unused2, *unused3, *unused4, *unused5;

  LIST  *stmts;                     /* list of all statements */
  const struct st_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.
  */
  my_bool *unbuffered_fetch_owner;
  /* needed for embedded server - no net buffer to store the 'info' */
  char *info_buffer;
  void *extension;
} MYSQL;
  • MYSQL 对象中的 methods 成员是一个结构体变量,该变量里面保存着很多函数指针,这些函数指针将会在数据库连接成功以后的各种数据操作中被调用。

创建 MySQL 对象

MYSQL* mysql_init(MYSQL *mysql);
  • 该函数用来分配或者初始化一个 MySQL 对象,用于连接 MySQL 服务器。
  • 如果传入的参数是 NULL,那么 mysql_init 将自动为你分配一个 MySQL 对象并返回。
  • 如果传入的参数是一个地址,那么 mysql_init 将在该地址处帮你完成初始化。

连接数据库

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 对象,该对象与第一个参数的值相同。
  • 如果连接数据库失败,则返回 NULL。

关闭数据库连接

void mysql_close(MYSQL *sock);

其中:

  • 该函数的参数,就是连接数据库前调用 mysql_init 创建的 MySQL 对象。
  • 如果传入的 MySQL 对象是 mysql_init 自动创建的,那么调用 mysql_close 时就会释放这个对象。

示例

在 MySQL 中首先有一个新用户:

grant all on curd_db.* to 'new_user'@'%' identified by '12345';

用户名是new_user%表示任意主机的用户,grant all表示它被授予所有权限在curd.db数据库下,密码是12345

在本地测试:

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

const string host = "localhost";
const string user = "new_user";
const string passwd = "12345";
const string db = "curd_db";
const int port = 3306;

int main()
{
	// 1、创建 MySQL 对象
	MYSQL *mySQL = mysql_init(nullptr);
	// 2、连接数据库
	if (mysql_real_connect(mySQL, host.c_str(), user.c_str(), passwd.c_str(), db.c_str(), port, nullptr, 0) == nullptr)
	{
		cerr << "数据库连接失败!" << endl;
		exit(1);
	}
	cout << "数据库连接成功!" << endl;

	// 3、关闭数据库
	mysql_close(mySQL);
	cout << "数据库关闭成功!" << endl;

	return 0;
}

编译并运行:

image-20240227190559910

发送命令

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

数用于向 MySQL 服务器发送一个查询或命令,执行指定的 SQL 语句。

参数说明:

  • MYSQL *mysql:指向 MYSQL 结构体的指针,这个结构体代表了与 MySQL 服务器的一个连接。
  • const char *stmt_str:要执行的 SQL 语句的字符串。

返回值:

  • 成功执行时,返回 0
  • 出现错误时,返回非 0 值。

设置编码格式

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

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

参数说明:

  • mysql: 表示在连接数据库前,调用 mysql_init 函数创建的 MySQL 对象。
  • csname: 表示要设置的编码格式,如"utf8"

返回值说明:

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

插入、删除或修改记录

在 mysql_query 函数中向 MySQL 发送 INSERT SQL:

int main()
{
    // ...
	cout << "数据库连接成功!" << endl;
	// 设置编码
	mysql_set_character_set(mySQL, "utf8");
	// 插入记录
	string sql = "insert into account values(4,'小李',30,400)";
	if (mysql_query(mySQL, sql.c_str()) != 0)
	{
		cout << "插入数据失败!" << endl;
		exit(2);
	}
	// ...
	return 0;
}

数据被成功插入到表中。

image-20240227193308014

类似地,可以删除和修改记录:

	string sql = "update account set balance=222 where id=2";
image-20240227193749866
	string sql = "delete from account where id=4";
image-20240227193844242

查询记录

对于 mysql_query 函数而言,插入、删除和修改操作都很简单,只要将 SQL 字符串作为参数传入即可,不需要返回值。但是 SELECT 查询需要返回结果,这需要使用到 MYSQL_RES 对象。

MYSQL_RES* mysql_store_result(MYSQL *mysql);
  • 该函数会调用指定 MySQL 对象中对应的函数指针来获取查询结果,并将获取到的查询结果保存到 MYSQL_RES 变量中进行返回。
  • 需要注意的是,MYSQL_RES 变量的内存空间是 malloc 出来的,因此在使用完后需要调用 free 函数进行释放,否则会造成内存泄露。

MYSQL_RES 变量中保存了查询得到的各种信息,其类型定义如下:

typedef struct st_mysql_res {
	my_ulonglong  row_count;
	MYSQL_FIELD	*fields;
	MYSQL_DATA	*data;
	MYSQL_ROWS	*data_cursor;
	unsigned long *lengths;		/* column lengths of current row */
	MYSQL		*handle;		/* for unbuffered reads */
    const struct st_mysql_methods *methods;
    MYSQL_ROW	row;			/* If unbuffered read */
    MYSQL_ROW	current_row;		/* buffer to current row */
    MEM_ROOT	field_alloc;
    unsigned int	field_count, current_field;
    my_bool	eof;			/* Used by mysql_fetch_row */
    /* mysql_stmt_close() had to cancel this result */
    my_bool       unbuffered_fetch_cancelled;
    void *extension;
} MYSQL_RES;

获取查询结果的行数:

my_ulonglong mysql_num_rows(MYSQL_RES *res);

获取查询结果的列数:

unsigned int mysql_num_fields(MYSQL_RES *res);

获取查询结果的列属性:

MYSQL_FIELD* mysql_fetch_fields(MYSQL_RES *res);

mysql_fetch_fields 函数将会返回多个 MYSQL_FIELD 对象,每个 MYSQL_FIELD 对象中保存着对应列的各种列属性,其类型定义如下:

typedef struct st_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;

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

MYSQL_ROW mysql_fetch_row(MYSQL_RES *result);

MYSQL_ROW 对象中保存着一行数据,这一行数据中可能包含多个字符串,对应就是这行数据中的多个列信息,因此 MYSQL_ROW 本质就是 char** 类型,其类型定义如下:

typedef char **MYSQL_ROW;		/* return data as array of strings */

示例

int main()
{
    // ...
	// 3、查询数据库表中的记录
	// a、执行查询语句
	string sql = "select * from account";
	if (mysql_query(mySQL, sql.c_str()) != 0)
	{
		cout << "查询数据失败!" << endl;
		exit(2);
	}
	cout << "查询数据成功!" << endl;
	// b、获取查询结果
	MYSQL_RES *res = mysql_store_result(mySQL);
	int rows = mysql_num_rows(res);	  // 数据的行数
	int cols = mysql_num_fields(res); // 数据的列数
	// 获取每列的属性并打印列名
	MYSQL_FIELD *fields = mysql_fetch_fields(res);
	for (int i = 0; i < cols; i++)
	{
		cout << fields[i].name << "\t";
	}
	cout << endl;
	for (int i = 0; i < rows; i++)
	{
		// 获取一行数据并进行打印
		MYSQL_ROW row = mysql_fetch_row(res);
		for (int j = 0; j < cols; j++)
		{
			cout << row[j] << "\t";
		}
		cout << endl;
	}
	// 释放内存空间
	free(res); 
    // ...
	return 0;
}

参考资料

  • Linux centos 7/ubantu 下: 用 C 语言连接 MySQL 数据库
  • MySQL 使用 C 语言连接

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1507303.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

明日周刊-第1期

打算开一个新的专栏&#xff0c;专门记录一周发生的事情以及资源共享&#xff0c;那么就从第一期开始吧。 1. 一周热点 人工智能技术突破&#xff1a;可能会有关于人工智能领域的最新研究成果&#xff0c;例如新算法的开发、机器学习模型的提升或者AI在不同行业的应用案例。 量…

PT:dmsa如何设置don‘t use

我正在「拾陆楼」和朋友们讨论有趣的话题,你⼀起来吧? 拾陆楼知识星球入口 往期文章链接: PT: 基于Multi Voltage的physical aware DMSA PT: DMSA remote_execute { \ define_user_attribu

Tomcat源码解析(四):StandardServer和StandardService

Tomcat源码系列文章 Tomcat源码解析(一)&#xff1a;Tomcat整体架构 Tomcat源码解析(二)&#xff1a;Bootstrap和Catalina Tomcat源码解析(三)&#xff1a;LifeCycle生命周期管理 Tomcat源码解析(四)&#xff1a;StandardServer和StandardService 文章目录 前言一、Standar…

大数据赋能,能源企业的智慧转型之路

在数字洪流中&#xff0c;大数据已经成为推动产业升级的新引擎。特别是在能源行业&#xff0c;大数据的应用正引领着一场深刻的智慧转型。今天&#xff0c;我们就来探讨大数据如何在能源企业中发挥其独特的魅力&#xff0c;助力企业提效降本&#xff0c;实现绿色发展。 动态监控…

R语言读取大型NetCDF文件

失踪人口回归&#xff0c;本篇来介绍下R语言读取大型NetCDF文件的一些实践。 1 NetCDF数据简介 先给一段Wiki上关于NetCDF的定义。 NetCDF (Network Common Data Form) is a set of software libraries and self-describing, machine-independent data formats that support…

光线追踪11 - Positionable Camera(可定位相机)

相机和介质一样&#xff0c;调试起来很麻烦&#xff0c;所以我总是逐步开发我的相机。首先&#xff0c;我们允许可调节的视野&#xff08;fov&#xff09;。这是渲染图像从一边到另一边的视觉角度。由于我们的图像不是正方形的&#xff0c;水平和垂直的视野是不同的。我总是使用…

mybatis基础操作(三)

动态sql 通过动态sql实现多条件查询&#xff0c;这里以查询为例&#xff0c;实现动态sql的书写。 创建members表 创建表并插入数据&#xff1a; create table members (member_id int (11),member_nick varchar (60),member_gender char (15),member_age int (11),member_c…

【探索程序员职业赛道:挑战与机遇】

💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学习,不断总结,共同进步,活到老学到老导航 檀越剑指大厂系列:全面总结 jav…

微信小程序(五十三)修改用户头像与昵称

注释很详细&#xff0c;直接上代码 上一篇 新增内容&#xff1a; 1.外界面个人资料基本模块 2.资料修改界面同步问题实现&#xff08;细节挺多&#xff0c;考虑了后期转服务器端的方便之处&#xff09; 源码&#xff1a; app.json {"window": {},"usingCompone…

什么是5G边缘计算网关?

随着5G技术的飞速发展和普及&#xff0c;边缘计算作为5G时代的关键技术之一&#xff0c;正日益受到业界的关注。而5G边缘计算网关&#xff0c;作为连接5G网络和边缘计算节点的桥梁&#xff0c;扮演着至关重要的角色。HiWoo Box&#xff0c;作为一款卓越的5G边缘计算网关&#x…

【Spring云原生系列】SpringBoot+Spring Cloud Stream:消息驱动架构(MDA)解析,实现异步处理与解耦合

&#x1f389;&#x1f389;欢迎光临&#xff0c;终于等到你啦&#x1f389;&#x1f389; &#x1f3c5;我是苏泽&#xff0c;一位对技术充满热情的探索者和分享者。&#x1f680;&#x1f680; &#x1f31f;持续更新的专栏《Spring 狂野之旅&#xff1a;从入门到入魔》 &a…

使用Spring的AOP

使用Spring的AOP 一、AOP 的常用注解1.切面类Aspect2.Pointcut3.前置通知Before4.后置通知AfterReturning5.环绕通知Around6.异常通知AfterThrowing7.最终通知After8.切面顺序Order9.启用自动代理EnableAspectJAutoProxy 二、AOP注解方式开发三、AOP 全注解开发四、基于XML配置…

RDD算子介绍(二)

1. coalesce 用于缩减分区&#xff0c;减少分区个数&#xff0c;减少任务调度成本。 val rdd : RDD[Int] sc.makeRDD(List(1, 2, 3, 4), 4) val newRDD rdd.coalesce(2) newRDD.saveAsTextFile("output") 分区数可以减少&#xff0c;但是减少后的分区里的数据分布…

Keepalived+LVS构建高可用集群

目录 一、Keepalive基础介绍 1. Keepalive与VRRP 2. VRRP相关技术 3. 工作原理 4. 模块 5. 架构 6. 安装 7. Keepalived 相关文件 7.1 配置组成 7.2 全局配置 7.3 VRRP实例配置&#xff08;lvs调度器&#xff09; 7.4 虚拟服务器与真实服务器配置 二、Keepalived…

【数据库】软件测试之MySQL数据库面试总结

有表如下&#xff1a; Student 学生表 SC 成绩表 Course 课程表 Teacher 老师表 每个学生可以学习多门课程&#xff0c;每一个课程都有得分&#xff0c;每一门课程都有老师来教&#xff0c;一个老师可以教多个学生 1、查询姓‘朱’的学生名单 select * from Student whe…

010Editor汉化版+下载+注册码+模板bug

项目场景&#xff1a; 这天我想使用我的不知名的一个破解版本的010Edit来查看一个EXE程序&#xff0c;并想使用模板功能&#xff0c;但是发现没有该模板还无法下载最新模板 问题描述 010Edit联网后需要注册码&#xff1a; 010 Editor 激活码生成器 使用方法 参照教程使用0…

面试题:分布式锁用了 Redis 的什么数据结构

在使用 Redis 实现分布式锁时&#xff0c;通常使用 Redis 的字符串&#xff08;String&#xff09;。Redis 的字符串是最基本的数据类型&#xff0c;一个键对应一个值&#xff0c;它能够存储任何形式的字符串&#xff0c;包括二进制数据。字符串类型的值最多可以是 512MB。 Re…

浅谈Maven

Maven能为我们解决什么问题 1&#xff1a;添加第三方jar包 按照最原始的做法&#xff0c;我们是手动复制jar包到项目WEB-INF/lib下&#xff0c;每个项目都会有一份&#xff0c;造成大量重复文件。而Maven将jar包放在本地仓库中统一管理&#xff0c;需要jar包只需要用坐标的方式…

使用Canvas绘制一个自适应长度的折线图

要求x轴根据数据长度自适应 y轴根据数据最大值取长度值 <template><div ref"cvsContainer" class"cvs-container"><canvas ref"cvs" class"canvas"></canvas></div> </template><script set…

188基于matlab的AR模型参数估计

基于matlab的AR模型参数估计&#xff0c;burg法和ule-Walker法估计信号&#xff0c;并输出估计误差。程序已调通&#xff0c;可直接运行。 188 AR模型参数估计 burg法和ule-Walker法 (xiaohongshu.com)