使用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.cc
	g++ $^ -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 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_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命令生成可执行程序,运行后在即可看到数据的查询结果

 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Django学习笔记

记个笔记 使用Django时使用python3.9创建app时没有响应 使用如下指令&#xff1a; python manage.py startapp app名字 原因&#xff1a; windows使用python运行时指令不是python3.9... 此外启动项目也是&#xff1a; python manage.py runserver 2023.7.8 使用Django链接…

计算机系统结构与操作系统实验三(4-2)-启动分页机制

&#x1f4cd;实验要求 在开启分页后&#xff0c;显示提示如“V-zhangsan” 用命令info tab查看虚拟地址向物理地址的映射情况 用命令creg显示控制位中PG页式是否开启 &#x1f4cd;实验过程 创建文件 &#x1f4cd;&#x1f4cd;mbr.S ;主引导程序 ;------------------…

大数据ETL工具对比(Sqoop, DataX, Kettle)

前言 在实习过程中&#xff0c;遇到了数据库迁移项目&#xff0c;对于数据仓库&#xff0c;大数据集成类应用&#xff0c;通常会采用ETL工具辅助完成&#xff0c;公司和客户使用的比较多的是Sqoop, DataX和Kettle这三种工具。简单的对这三种ETL工具进行一次梳理。 ETL工具&…

Day2 图连通

A - PRO-Professor Szu 简单的来说就是 缩点、反图拓扑。 需要注意不与 n 1 n1 n1 联通的点可能会使得一些点的入度无法为 0 而无法入队&#xff0c;消除这些点的影响即可。 当时写的&#xff1a; D - BLO-Blockade 非割点&#xff1a; 2 ( n − 1 ) 2(n-1) 2(n−1)。 …

数据库主从同步

目录 一、准备工作1.1 安装或关闭以下服务1.2 本次安装环境 2、主数据库配置2.1主数据库配置2.2创建用户2.3查看信息 三、从主数据库配置3.1从数据库配置3.2连接主服务器3.3测试 4、其他4.1连接完毕后发现Slave_IO_Running值异常&#xff0c;4.2报错Error connecting to source…

Coggle 30 Days of ML (23年7月)任务二:数据可视化

Coggle 30 Days of ML (23年7月&#xff09;任务二&#xff1a;数据可视化 任务二&#xff1a;对数据集字符进行可视化&#xff0c;统计标签和字符分布 说明&#xff1a;在这个任务中&#xff0c;需要使用Pandas库对数据集的字符进行可视化&#xff0c;并统计数据集中的标签和…

深入了解C语言中scanf()函数的用法

目录 正文 一、基本用法 二、格式化字符串 三、多个输入值 四、错误处理 五、总结 正文 在C语言中&#xff0c;scanf()函数是一个非常有用的输入函数&#xff0c;它允许我们从用户那里获取输入&#xff0c;并将输入存储到指定的变量中。本文将详细介绍scanf()函数的使用方…

基于单片机停车场刷卡收费的设计与实现

功能介绍 以51单片机作为主控系统&#xff1b;通过液晶显示当前时间&#xff0c;车位、剩余车位、时间等信息&#xff1b;进电机正反转表示开关门&#xff1b;按键可以设置当前时间/单价/分钟&#xff1b;RC522射频卡识别&#xff0c;当刷卡后模拟汽车驶入&#xff0c;开始收费…

驱动开发-day10

驱动代码&#xff1a; #include <linux/cdev.h> #include <linux/device.h> #include <linux/fs.h> #include <linux/gpio.h> #include <linux/init.h> #include <linux/interrupt.h> #include <linux/mod_devicetable.h> #include …

OpenCV 入门教程:轮廓特征和轮廓匹配

OpenCV 入门教程&#xff1a;轮廓特征和轮廓匹配 导语一、轮廓特征二、轮廓匹配三、示例应用3.1 目标识别3.2 形状分析 总结 导语 轮廓特征和轮廓匹配是图像处理中用于描述和比较轮廓的技术。通过提取轮廓的形状、面积、周长等特征&#xff0c;并进行比较和匹配&#xff0c;我…

Python+Requests+Excel接口测试实战

1、EXCEL文件接口保存方式&#xff0c;如图。 2、然后就是读取EXCEL文件中的数据方法&#xff0c;如下&#xff1a; 1 import xlrd2 3 4 class readExcel(object):5 def __init__(self, path):6 self.path path7 8 property9 def getSheet(self): 10 …

flutter开发实战-Running Gradle task ‘assembleDebug‘ 的解决方法

flutter开发实战-Running Gradle task ‘assembleDebug‘ 的解决方法 使用Android studio经常出现Running Gradle task ‘assembleDebug‘问题&#xff0c;记录一下解决方法。 一、在Android目录下更改build.gradle 将repositories中的google(), mavenCentral() repositori…

从钢铁行业数字化管控平台的智能进化,看超自动化能力边界

文/王吉伟 钢铁行业的数字化转型&#xff0c;历来都是值得探讨的热点话题。 2022年&#xff0c;我国粗钢产量10.13亿吨&#xff0c;占据了全球钢铁供给市场的半壁江山。 这组数据可谓非常抢眼&#xff0c;但仍旧难掩诸多企业的各种经营问题。 钢铁生产过程工序众多&#xf…

计算机网络-网络层上篇

目录 一、网络层概述 二、网络层提供的两种服务 &#xff08;一&#xff09;面向连接的虚电路服务 &#xff08;二&#xff09;无连接的数据报服务 &#xff08;三&#xff09;虚电路服务与数据报服务的比较 三、IPv4地址及其应用 &#xff08;一&#xff09;IPv4地址概…

python中的生成器(generator)

一、生成器 生成器是 Python 中非常有用的一种数据类型&#xff0c;它可以让你在 Python 中更加高效地处理大量数据。生成器可以让你一次生成一个值&#xff0c;而不是一次生成一个序列&#xff0c;这样可以节省内存并提高性能 二、实现generator的两种方式 python中的gener…

SuperMap iClient3D for Cesium最短路径分析

作者&#xff1a;Mei 目录 前言实现思路实现步骤1、构建二维网络数据集1.1拓扑检查1.2线拓扑数据集处理1.3构建二维网络数据集 2、发布网络分析服务3、实现代码 前言 在交通、消防业务场景中&#xff0c;如果某地发生火灾或者交通事故&#xff0c;需要快速规划出最短抢救路线&a…

flask计算pin码

目录 Flask计算pin码 <1> 概念 什么是pin码&#xff1f; pin码生成条件&#xff1f; 读取相关文件绕过过滤 <2> 源码分析 werkzeug 1.0.x版本 计算PIN的源码 werkzeug 2.0.x版本 计算PIN的源码 <3> 计算生成pin的脚本 CTF中 flask-pin的应用 <1…

volatile原理剖析和实例讲解

一、是什么 volatile是Java的一个关键字&#xff0c;是Java提供的一种轻量级的同步机制&#xff0c; 二、能做什么 保证了不同线程对这个变量进行操作时的可见性&#xff0c;有序性。 三、可见性 可见性主要是指一个线程修改了共享变量的值&#xff0c;另一个线程可以看见…

RPC 框架架构设计

RPC 框架架构设计 RPC 又称远程过程调用&#xff08;Remote Procedure Call&#xff09;&#xff0c;用于解决分布式系统中服务之间的调用问题。通俗地讲&#xff0c;就是开发者能够像调用本地方法一样调用远程的服务。下面我们通过一幅图来说说 RPC 框架的基本架构。 RPC 框架…

Python_与redis数据库交互

目录 redis模块的使用 连接方式 连接池 操作 设置值 获取值 管道 事务 源码等资料获取方法 python可以使用redis模块来跟redis交互 redis模块的使用 安装模块: pip3 install redis 导入模块&#xff1a;import redis 连接方式 严格连接模式&#xff1a;rredis.St…