C语言连接【MySQL】

稍等更新图片。。。。

文章目录

  • 安装 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.mzph.cn/news/734864.shtml

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

相关文章

关于查看 CentOS7虚拟机的 ip地址

1. 启动网卡 1.1 打开网卡配置文件。 vi /etc/sysconfig/network-scripts/ifcfg-eth01.2 启动网卡 修改为下图中的ONBOOTyes 2. 重启网络服务 sudo service network restart3. 查看ip地址 ip addr

MySQL8.0数据库开窗函数

简介 数据库开窗函数是一种在SQL中使用的函数&#xff0c;它可以用来对结果集中的数据进行分组和排序&#xff0c;以便更好地分析和处理数据。开窗函数与聚合函数不同&#xff0c;它不会将多行数据聚合成一行&#xff0c;而是保留每一行数据&#xff0c;并对其进行分组和排序。…

HellaSwag数据集分享

来源: AINLPer公众号&#xff08;每日干货分享&#xff01;&#xff01;&#xff09; 编辑: ShuYini 校稿: ShuYini 时间: 2024-3-10 该数据集是由斯坦福大学研究人员提出的&#xff0c;用于评估NLP模型在常识自然语言推理&#xff08;NLI&#xff09;任务上的性能&#xff0c;…

凌鲨微应用架构

微应用是静态网页加上凌鲨提供的扩展能力而形成的一种应用&#xff0c;主要特点是开发便捷&#xff0c;安全。 微应用架构 组件说明 名称 说明 微应用 webview窗口&#xff0c;显示web服务器上的页面 接口过滤器 根据权限配置,屏蔽非授权接口访问 接口提供者 tauri注入…

一个开源免费的实时AI绘画软件Krita

Krita是由Krita插件ComfyUILCM插件结合的一个实时可预览的AI绘画工具&#xff0c;是一款自由开源、免费的专业级绘画软件&#xff0c;Krita采用的是GNU GPL许可证确保它将一直保持自由开源的本色。 一&#xff1a;搭建Krita创作平台 1、Krita客户端软件&#xff0c;该软件下载…

乡村治理深度解析:策略、挑战与解决方案

毋庸置疑&#xff0c;在今天这个崭新的时代&#xff0c;乡村治理的过程已然向我们发出了挑战。为了迎难而上&#xff0c;我们必须摒弃陈旧观念&#xff0c;勇敢迎接并大胆尝试探索与实践新的思路&#xff01;为了达到这一宏伟目标&#xff0c;我们需要首先廓清如下关键概念&…

新一代电话机器人正式上线

演示账户 代理商演示账户 地址&#xff1a;http://119.23.229.15:8080 用户名&#xff1a;c0508 密码&#xff1a;123456 功能&#xff1a;包含AI外呼管理&#xff0c;话术管理&#xff0c;CRM管理&#xff0c;坐席管理等功能。 管理员演示账户&#xff1a; 地址&#xff1a;h…

拥塞控制的作用和方法

目录 1.概念 2.慢启动 3.快速恢复 4.快速重传 1.概念 TCP数据流的控制. 为了保证可靠传输和提高网络通信质量,内核需要对TCP数据流进行控制 TCP数据流控制的两个方面:超时重传和拥塞控制, 在计算机网络中的链路容量(即带宽)、交换结点中的缓存和处理机等&#xff0c;都是…

复合查询【MySQL】

文章目录 复合查询测试表 单表查询多表查询子查询单行子查询多行子查询IN 关键字ALL 关键字ANY 关键字 多列子查询 合并查询 复合查询 测试表 雇员信息表中包含三张表&#xff0c;分别是员工表&#xff08;emp&#xff09;、部门表&#xff08;dept&#xff09;和工资等级表&…

OS-Copilot:实现具有自我完善能力的通用计算机智能体

&#x1f349; CSDN 叶庭云&#xff1a;https://yetingyun.blog.csdn.net/ AI 缩小了人类间的知识和技术差距 论文标题&#xff1a;OS-Copilot: Towards Generalist Computer Agents with Self-Improvement 论文链接&#xff1a;https://arxiv.org/abs/2402.07456 项目主页&a…

【工具相关】zentao用例管理平台部署实践

文章目录 一、备份还原1、数据备份1.1、前言1.2、版本备份1.3、数据备份 2、数据恢复2.1、版本恢复2.2、数据恢复 二、问题处理1、ERROR: SQLSTATE[HY000] [2002] Connection refused 一、备份还原 1、数据备份 1.1、前言 禅道系统从10.6版本以后&#xff0c;新增数据备份设…

Go语言必知必会100问题-20 切片操作实战

前言 有很多gopher将切片的length和capacity混淆&#xff0c;没有彻底理清这两者的区别和联系。理清楚切片的长度和容量这两者的关系&#xff0c;有助于我们合理的对切片进行初始化、通过append追加元素以及进行复制等操作。如果没有深入理解它们&#xff0c;缺少高效操作切片…

云服务器python版本冲突解决(awd平台搭建)

文章目录 yum和apt-getdockerpython环境问题 大家在使用python时&#xff0c;难免会使用他人的代码&#xff0c;自己是python3&#xff0c;而别人的是python2.我们直接运行会报错(比如print函数括号的问题)。但是去修改代码又很麻烦。这里给大家推荐conda。我以我搭建awd平台为…

【Java.mysql】——增删查改(CRUD)之 增查(CR) 附加数据库基础知识

目录 &#x1f6a9;数据库操作 &#x1f388;创建数据库 &#x1f388;使用数据库 &#x1f388;删除数据库 &#x1f6a9;数据类型 &#x1f6a9;表的操作 &#x1f388;创建表 &#x1f308;查看表结构 &#x1f388;删除表 ❗练习(综合运用) &#x1f5a5;️新增…

微信小程序提示确认框

如图所示&#xff0c;如何弹出微信小程序自带默认弹框&#xff1f; 代码如下&#xff1a; wx.showModal({ title: 确认, content: 确定要删除吗&#xff1f;, success (res) { if (res.confirm) { console.log(用户点击确定) } else if (res.cancel) { console.log(用…

STM32CubeIDE基础学习-STM32CubeIDE软件程序仿真调试

STM32CubeIDE基础学习-STM32CubeIDE软件程序仿真调试 前言 一般编写完程序后都会进行编译&#xff0c;看结果是否有存在语法错误&#xff0c;确认没有语法错误之后再进行代码的下载观察硬件执行是否和软件编程预期的结果一致&#xff0c;如果发现硬件执行达不到预期现象&#…

JWT令牌技术

写在前面 我以为&#xff0c;最美的日子&#xff0c;当是晨起侍花&#xff0c;闲来煮茶&#xff0c;阳光下打盹&#xff0c;细雨中漫步&#xff0c;夜灯下读书&#xff0c;在这清浅时光里&#xff0c;一半烟火&#xff0c;一半诗意&#xff0c;任窗外花开花落&#xff0c;云来云…

no main manifest attribute,in xxx.jar(关于Spring项目,无法在云服务器上运行jar包的解决方法)

目录 问题详情 解决方法 问题详情 项目可以打包正常&#xff0c;但是云服务器上无法运行&#xff0c;报错&#xff1a;no main manifest attribute&#xff0c;in xxx.jar 解决方法 1.查看pom.xml配置文件&#xff0c;检查以下代码&#xff0c;没有则加上&#xff1a; <…

B+树 和 跳表 的结构及区别,不同的用途【mysql的索引为什么使用B+树而不使用跳表?】

导语&#xff1a; 详解B树与跳表的结构及区别&#xff0c;描述B树与跳表新增数据的过程&#xff0c;解释MySQL与Redis选择对应结构的原因。 mysql数据表里直接遍历这一行行数据&#xff0c;性能就是O(n)&#xff0c;比较慢。为了加速查询&#xff0c;使用了B树来做索引&#x…

HTML5 Web Worker之性能优化

描述 由于 JavaScript 是单线程的&#xff0c;当执行比较耗时的任务时&#xff0c;就会阻塞主线程并导致页面无法响应&#xff0c;这就是 Web Workers 发挥作用的地方。它允许在一个单独的线程&#xff08;称为工作线程&#xff09;中执行耗时的任务。这使得 JavaScript 代码可…