使用C语言连接MySQL

目录

一、引入库

1.1 下载库文件

1.2 在项目中引入库

二、使用库

2.1 连接数据库

2.2 SQL请求

2.3 获取查询结果

2.4 使用案例


一、引入库

1.1 下载库文件

要使用C语言连接MySQL,需使用MySQL官网提供的库

MySQL :: Download Connector/C++https://dev.mysql.com/downloads/connector/cpp/

上传到云服务器

下载完毕后将其上传到云服务器即可。下面将下载的库文件解压后存放在一个名为makeuse的目录中

进入解压后的目录中,可以看到有一个include子目录和一个lib子目录

include目录下存放的是一批头文件

bin目录下存放的是动静态库

1.2 在项目中引入库

为了方便在项目中使用刚才的库文件,可以在项目目录下创建两个软连接,分别连接到刚才的include目录和lib目录

此时在项目目录下,就能直接看到刚才include和lib目录下的内容

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

#include <iostream>
#include <mysql.h>
using namespace std;int main()
{//获取客户端的版本信息cout<<"mysql client version: "<<mysql_get_client_info()<<endl;return 0;
}

为了方便后续重复编译源文件,在项目目录下创建一个makefile

mysqlConnect:mysqlConnect.ccg++ $^ -o $@ -std=c++11 -I./include -L./lib -lmysqlclient
.PHONY:clean
clean:rm -rf mysqlConnect 
  • -I:指明头文件的搜索路径
  • -L:指明库文件的搜索路径
  • -l:指明需要连接库文件路径下的哪一个库

makefile编写完毕后,使用make命令编译代码生成可执行程序

但此时生成的可执行程序还不能直接运行,通过ldd命令可以发现,该可执行程序所依赖的mysqlclient库找不到

  • gcc/g++编译器默认都是动态链接,编译代码时默认使用动态库,所以生成的可执行程序在运行时需要找到对应的动态库进行链接,而使用的mysqlclient库并不在系统的搜索路径下
  • Makefile中的-I,-L和-l这三个选项,只是在编译期间告诉编译器头文件和库文件在哪里,而可执行程序生成后就与编译器无关了

动态库如何使用,在《Linux动静态库》这篇文章中讲解过,不知道如何配置的可以参考下面这篇文章

(28条消息) Linux动静态库_GG_Bond19的博客-CSDN博客icon-default.png?t=N658https://blog.csdn.net/GG_Bruse/article/details/128810497配置完成后可执行程序所依赖的mysqlclient库就能够被找到了

运行可执行程序后,可以看到客户端的版本为6.1.11,即刚才下载的库文件的版本

二、使用库

2.1 连接数据库

创建MySQL对象

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

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 flagfrom 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_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时就会释放这个对象

2.2 SQL请求

下发SQL请求

int	mysql_query(MYSQL *mysql, const char *q);
  • mysql: 表示在连接数据库前,调用mysql_init函数创建的MySQL对象
  • q: 表示向MySQL服务器下发的SQL请求,SQL最后可以不带分号

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

设置编码格式

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

int mysql_set_character_set(MYSQL *mysql, const char *csname);
  • mysql: 表示在连接数据库前,调用mysql_init函数创建的MySQL对象
  • csname: 表示要设置的编码格式,如"utf8"

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

2.3 获取查询结果

  • 对数据库中的数据进行增删改操作时,都只需调用mysql_query向服务器下发对应的SQL请求
  • 而对数据库中的数据进行查询操作时,除了需要调用mysql_query向服务器下发对应的查询SQL,还需获取查询结果

获取查询结果

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

获取查询结果的行数

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

my_ulonglong mysql_num_rows(MYSQL_RES *res);

获取查询结果的列数

该函数会从指定的MYSQL_RES对象中,获取查询结果的列数

unsigned int mysql_num_fields(MYSQL_RES *res);

获取查询结果的列属性

该函数会从指定的MYSQL_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 */

2.4 使用案例

查询user表中的数据并进行打印输出

#include <iostream>
#include <string>
#include <mysql.h>
using namespace std;const string host = "43.139.44.157";
const string passwd = "123qwe@@@QWE";
const string user = "bjy";
const string db = "olinejudge";
const int port = 3306;int main()
{//1、获取MySQL实例(相当于创建了一个MySQL句柄)MYSQL* ms = mysql_init(nullptr);//2、连接数据库if(mysql_real_connect(ms, host.c_str(), user.c_str(), passwd.c_str(), db.c_str(), port, nullptr, 0) == nullptr) {cerr<<"数据库连接失败!"<<endl;return 1;}cout<<"数据库连接成功!"<<endl;mysql_set_character_set(ms, "utf8"); //设置编码格式为utf8//3、查询数据库表中的记录//a、执行查询语句string sql = "select * from user";if(mysql_query(ms, sql.c_str()) != 0) {cout<<"查询数据失败!"<<endl;return 2;}cout<<"查询数据成功!"<<endl;//b、获取查询结果MYSQL_RES* res = mysql_store_result(ms);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); //释放内存空间//4、关闭数据库mysql_close(ms);cout<<"数据库关闭成功!"<<endl;return 0;
}

使用make命令生成可执行程序,运行后在即可看到数据的查询结果

 

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

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

相关文章

unbuntu 22.04 安装和卸载企业微信

every blog every motto: You can do more than you think. https://blog.csdn.net/weixin_39190382?typeblog 0. 前言 记录有关在ubuntu22.04上安装和卸载企业微信 以及企业微信无法打开问题处理 1. 正文 1.1 安装 下载wine环境 http://archive.ubuntukylin.com/softwar…

【动手学习深度学习--逐行代码解析合集】15卷积神经网络(LeNet)

【动手学习深度学习】逐行代码解析合集 15卷积神经网络&#xff08;LeNet&#xff09; 视频链接&#xff1a;动手学习深度学习–卷积神经网络&#xff08;LeNet&#xff09; 课程主页&#xff1a;https://courses.d2l.ai/zh-v2/ 教材&#xff1a;https://zh-v2.d2l.ai/ 1、LeN…

IDEA中 application.yaml文件没有绿色的叶子

IDEA中 application.yaml文件没有绿色的叶子 问题背景 前段时间一直在刷算法题和备战考试&#xff0c;忽略了项目方面的锻炼&#xff0c;于是今天就想着来写一个练手的项目&#xff0c;重新熟悉一下技术栈。结果刚搭建一个SpringBoot项目&#xff0c;就发现application.yaml配…

第三方ipad电容笔哪个品牌好用?平板电容笔推荐

可能很多人都认为&#xff0c;苹果原装的电容笔&#xff0c;是不可取代&#xff0c;但我认为&#xff0c;这还要看个人的预算&#xff0c;以及实际的需求。苹果Pencil对于那些不太讲究画质的用户来说实在是太贵了&#xff0c;要是我们仅用于书写上&#xff0c;其实我们可以用平…

java动态导出excel头

java动态导出excel头 java根据动态头导出excel文件一、需求背景1、调用接口将表头传给给后端2、请求结果展示3、核心代码1、工具类&#xff0c;注意异常抛出类如报错&#xff0c;需自定义异常类2、标题设置类3、单元各简单设置类4、controller接收参数 java根据动态头导出excel…

LeetCode 203. 移除链表元素

给你一个链表的头节点 head 和一个整数 val &#xff0c;请你删除链表中所有满足 Node.val val 的节点&#xff0c;并返回 新的头节点 。 &#xff08;1&#xff09;直接使用原来的链表来进行移除节点操作&#xff1a; //不带头结点删除元素节点 class Solution { public:Lis…

ssh配置多账号(Mac)

一. 应用场景 当存在同时需要git在GitHub、gitee、gitlab等多个不同git托管平台进行ssh代码操作的时候。 二. 具体操作 默认 ssh-keygen -t rsa -C "你的邮箱"之后一直回车就可以&#xff0c;会默认在~/.ssh目录下生成id_rsa、id_rsa.pub 指定文件 ssh-keygen …

Git Commit的规范及高级使用方法

git commit是日常工作中使用率极高的一个命令&#xff0c;但是根据我从业5年的经验来看&#xff0c;大多数人在用git commit命令时都很粗糙&#xff0c;比如git commit -m 后跟的message是五花八门&#xff0c;有用中文的&#xff0c;有用英文的&#xff0c;甚至还有直接跟111的…

Codeforces Round 882 (Div. 2)(视频讲解A——D)

[TOC](Codeforces Round 882 (Div. 2)&#xff08;视频讲解A——D&#xff09;) 讲解在B站&#xff1a;Codeforces Round 882 (Div. 2)&#xff08;视频讲解A——D&#xff09; A The Man who became a God #include<bits/stdc.h> #define endl \n #define INF 0x3f3…

【分布式应用】zookeeper集群

目录 一、zookeeper概述1.1zookeeper工作机制1.2Zookeeper 数据结构1.3Zookeeper 应用场景1.4Zookeeper 选举机制第一次启动选举机制**非第一次启动选举机制 二、部署 Zookeeper 集群2.1环境配置2.2安装 Zookeeper 一、zookeeper概述 Zookeeper是一个开源的分布式的&#xff0c…

机械臂与RealSense相机手眼标定

环境&#xff1a; 本文主要使用kinova mico机械臂 RealSense D435i深度相机进行了eye to hand的手眼标定。 系统环境&#xff1a;Ubuntu18.04&#xff0c;ROS Melodic 硬件&#xff1a;Kinova mico&#xff0c;RealSense D435i 特别注意&#xff1a;经测试&#xff0c;本方法…

【Python】Python实现串口通信(Python+Stm32)

&#x1f389;欢迎来到Python专栏~Python实现串口通信 ☆* o(≧▽≦)o *☆嗨~我是小夏与酒&#x1f379; ✨博客主页&#xff1a;小夏与酒的博客 &#x1f388;该系列文章专栏&#xff1a;Python学习专栏 文章作者技术和水平有限&#xff0c;如果文中出现错误&#xff0c;希望…