【MySQL】使用C/C++访问MySQL

news2024/11/17 0:08:19

文章目录

  • 一. 环境准备
    • 1. 方法一
    • 2. 方法二
  • 二. MySQL接口介绍
    • 1. 初始化/连接/关闭
    • 2. 执行操作
    • 3. 查找操作
  • 结束语

本篇环境是云服务器Centos上的MySQL
版本;
在这里插入图片描述

一. 环境准备

使用C/C++访问MySQL,首先需要MySQL的开发者库

这里提供两种方法:

1. 方法一

在MySQL的官网下载
MtySQL Community Downloads

  • 在这里插入图片描述

红框里的是各种语言的开发者包,本篇博客介绍C语言的接口,也就是C API

  • 在这里插入图片描述

选择和要访问的MySQL服务器一样环境,版本的开发者包

  • 在这里插入图片描述

Archives可以看到历史版本
注意不要下载成Debug版本

下载完成后,在云服务上使用rz命令将Windows的文件拷贝到云服务上
在这里插入图片描述
使用tar xzf 压缩包解压,然后可以再改个名

里面有很多的库文件,我们主要使用include里的mysql.h

第一种方法先介绍到这

2. 方法二

如果你的MySQL是通过yum源安装的,那么yum在安装MySQL的同时,已经帮我们下好了开发者工具,并且配置好了

头文件默认放在/usr/include/mysql
动静态库在/lib64/mysql

如果没有,使用以下命令安装

yum install mysql-devel

第三方库的使用可以移步【Linux】动静态库

这里简要说一下使用
gcc/g++默认搜索的头文件路径是/user/include
默认搜索的库路径是

  • /usr/local/lib
  • /usr/lib
  • /lib

编译可执行时需要如下命令

g++ -o -std=c++11 -I/usr/include/mysql -L/lib64/mysql -lmysqlclient

-I选项:指认使用的头文件。如果代码中#include<mysql/mysql.h>,其实可以不带-I选项,因为g++找得到
-L选项:指认库路径
-l:指认链接的库的名字


简单使用

makefile

mytest:test.cc
	g++ -o $@ $^ -std=c++11 -L/lib64/mysql -lmysqlclient
.PHONY:clean
clean:
	rm -f mytest

test.cc

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

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

    return 0;
}

mysql_get_client_info()是mysql.h中的一个函数,可以获取和次开发包相应对应的mysql客户端版本

在这里插入图片描述

运行成功

二. MySQL接口介绍

1. 初始化/连接/关闭

C API的各种接口和变量都可以在官方文档查找
MySQL官方文档(全)
下拉找到Conectors&APIs,可以找到C API,选择合适的版本C API 8.0

左侧的C API Basic Interface里的C API Funciton-reference是各函数C API函数
C API Basic Data Structures是各种变量,结构体C API结构体

MySQL本质是网络服务
C API使用MYSQL结构体管理客户端与服务器的链接等信息

初始化MYSQL结构体

MYSQL * mysql_init(MYSQL*mysql)

参数可以传nullptr,如果传入一个MYSQL,则会重置此MYSQL,结果都是返回一个新的MYSQL

链接MySQL

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是C API中一个非常重要的变量,里面内容非常丰富,有port,dbname,charset等链接基本参数,也包含一个st_mysql_methods的结构体变量,里面保存着很多函数指针,这些函数指针将会在数据库连接成功后的各种数据库操作中调用

如下是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;
  • host:链接的MySQL服务器的主机IP
  • user:登录的用户
  • passwd:用户密码
  • db:使用的数据库
  • port:MySQL服务器的端口号
  • unix_socket:域间套接字(管道通信),通常为nullptr
  • clientflag:通常为0,其他设置可查看官网

连接成功会将host,port等信息绑定到MYSQL中
失败则返回空指针

可以在MySQL中使用show processlist查看当前连接的用户

关闭连接

void mysql_close(MYSQL*mysql);

2. 执行操作

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

mysql:要哪个连接执行
sql:具体的sql语句

成功返回0,失败返回非0

案例:

准备了一个用户名为’ljh’,密码为123456,登录方式为localhost的用户
因为本地连接,所以IP使用本地环回127.0.0.1
端口号默认为3306
使用test数据库,其中有一个user表
表结构如下:

mysql> desc user;
+-----------+-------------+------+-----+---------+----------------+
| Field     | Type        | Null | Key | Default | Extra          |
+-----------+-------------+------+-----+---------+----------------+
| id        | int(11)     | NO   | PRI | NULL    | auto_increment |
| name      | varchar(10) | YES  |     | NULL    |                |
| age       | int(11)     | YES  |     | NULL    |                |
| telephone | varchar(11) | YES  | UNI | NULL    |                |
+-----------+-------------+------+-----+---------+----------------+

连接代码如下:

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

const std::string host ="127.0.0.1";
const std::string user="ljh";
const std::string passwd="123456";
const std::string db="test";
const unsigned int port=3306;


int main()
{
    //初始化
    MYSQL*conn=mysql_init(nullptr);
    if(conn==nullptr)
    {
        //初始化失败
        std::cerr<<"mysql init error"<<std::endl;
        return 1;
    }

    //建立连接
    conn=mysql_real_connect(conn,host.c_str(),user.c_str(),passwd.c_str(),db.c_str(),port,nullptr,0);
    if(conn==nullptr)
    {
        std::cerr<<"mysql connect error"<<std::endl;
        return 2;
    }

    std::cout<<"mysql connect success"<<std::endl;

    //关闭连接
    mysql_close(conn);

    return 0;
}

insert操作
在建立连接成功后

	const std::string sql="insert into user (name,age,telephone) values ('zhangsan',23,'123456')";
    int n=mysql_query(conn,sql.c_str());
    if(n==0)
    {
        std::cout<<sql<<" success "<<std::endl;
    }
    else
    {
        std::cerr<<"sql error"<<std::endl;
        return 3;
    }
mysql> select * from user;
Empty set (0.01 sec)

mysql> select * from user;
+----+----------+------+-----------+
| id | name     | age  | telephone |
+----+----------+------+-----------+
|  1 | zhangsan |   23 | 123456    |
+----+----------+------+-----------+

delete和update操作同理,只需要更改一下sql就可以了


编码格式

但是如果插入的是汉字,则会出现乱码的现象

const std::string sql="insert into user (name,age,telephone) values ('张三',23,'654321')";
mysql> select * from user;
+----+---------------+------+-----------+
| id | name          | age  | telephone |
+----+---------------+------+-----------+
|  1 | zhangsan      |   23 | 123456    |
|  4 | å¼ ä¸‰        |   23 | 654321    |
+----+---------------+------+-----------+

原因是开发者包默认使用的编码格式Latin1,MySQL默认使用utf8

更改编码格式

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

csname:指明编码格式

在建立连接后设置

mysql_set_character_set(conn,"utf8");
mysql> select * from user;
+----+----------+------+-----------+
| id | name     | age  | telephone |
+----+----------+------+-----------+
|  1 | zhangsan |   23 | 123456    |
|  5 | 张三     |   23 | 654321    |
+----+----------+------+-----------+

3. 查找操作

如果执行的sql语句是select,那么还需要调出结果
select语句通过mysql_query执行成功后,结果会放到MYSQL中,但为了更好的遍历,我们需要将结果拷贝到MYSQL_RES结果集中。

函数如下:

MYSQL_RES* mysql_store_result(MYSQL*mysql)

在这里插入图片描述

MYSQL_RES可以理解为一个char**的数组,一行数据其实就是一个char **
因为约束,所以MySQL的表数据时规整的,可以使用循环遍历

获取结果集的行数

uint64_t mysql_num_rows(MYSQL_RES *result)

获取结果集的列数

unsigned int mysql_num_fields(MYSQL_RES *result)

行迭代器 MYSQL_ROW
MYSQL_ROW就是char**

typedef char **MYSQL_ROW;

函数如下

MYSQL_ROW mysql_fetch_row(MYSQL_RES*res);

注意此处返回的是结构体对象,不是指针
每次调用这个函数后,下次调用都会将MYSQL_ROW定位到下一行数据

该函数会调用MYSQL变量中的st_mysql_methods中的read_rows函数指针来获取查询结果。同时malloc一片内存空间来存储查询到的数据,所以后续需要free释放这段空间

void mysql_free_result(MYSQL_RES *result)

案例:

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

const std::string host ="127.0.0.1";
const std::string user="ljh";
const std::string passwd="123456";
const std::string db="test";
const unsigned int port=3306;


int main()
{
    //初始化
    MYSQL*conn=mysql_init(nullptr);
    if(conn==nullptr)
    {
        //初始化失败
        std::cerr<<"mysql init error"<<std::endl;
        return 1;
    }

    //建立连接
    conn=mysql_real_connect(conn,host.c_str(),user.c_str(),passwd.c_str(),db.c_str(),port,nullptr,0);
    if(conn==nullptr)
    {
        std::cerr<<"mysql connect error"<<std::endl;
        return 2;
    }
    std::cout<<"mysql connect success"<<std::endl;
    mysql_set_character_set(conn,"utf8");//设置编码格式

    const std::string sql="select * from user";
	
	//执行sql语句
    int n=mysql_query(conn,sql.c_str());
    if(n==0)
    {
        std::cout<<sql<<" success "<<std::endl;
    }
    else
    {
        std::cerr<<"sql error"<<std::endl;
        return 3;
    }
    
    //获取结果集
    MYSQL_RES* res=mysql_store_result(conn);
    if(res==nullptr)
    {
        std::cerr<<"store error"<<std::endl;
        return 4;
    }

    int row=mysql_num_rows(res);//行数
    int field=mysql_num_fields(res);//列数
	//遍历
    for(int i=0;i<row;++i)
    {
        MYSQL_ROW rows=mysql_fetch_row(res);
        for(int j=0;j<field;++j)
        {
            std::cout<<rows[j]<<"\t";
        }
        std::cout<<std::endl;
    }

	mysql_free_result(res);

    //关闭连接
    mysql_close(conn);

    return 0;
}

在这里插入图片描述


获取列属性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_FIELD获取列名,列属性等信息

案例:

	MYSQL_FIELD*fields=mysql_fetch_field(res);
    for(int i=0;i<field;++i)
    {
        std::cout<<"列名:"<<fields[i].name<<std::endl;
    }

在这里插入图片描述

结束语

感谢看到此处
如果觉得本篇文章对你有所帮助的话,不妨点个赞支持一下博主,拜托啦,这对我真的很重要。
在这里插入图片描述

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

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

相关文章

【Unity每日一记】“调皮的协程”,协程和多线程的区别在哪里

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;元宇宙-秩沅 &#x1f468;‍&#x1f4bb; hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍&#x1f4bb; 本文由 秩沅 原创 &#x1f468;‍&#x1f4bb; 收录于专栏&#xff1a;uni…

【MySQL系列】 第二章 · SQL(下)

写在前面 Hello大家好&#xff0c; 我是【麟-小白】&#xff0c;一位软件工程专业的学生&#xff0c;喜好计算机知识。希望大家能够一起学习进步呀&#xff01;本人是一名在读大学生&#xff0c;专业水平有限&#xff0c;如发现错误或不足之处&#xff0c;请多多指正&#xff0…

JSP运行环境搭建

将安装JSP引擎的计算机称作一个支持JSP的Web服务器。这个服务器负责运行JSP&#xff0c;并将运行结果返回给用户。 JSP的核心内容之一就是编写JSP页面,JSP页面是Web应用程序的重要组成部分之一。一个简单Web应用程序可能只有一个JSP页面,而一个复杂的Web应用程序可能由许多JSP…

【操作系统】考研真题攻克与重点知识点剖析 - 第 3 篇:内存管理

前言 本文基础知识部分来自于b站&#xff1a;分享笔记的好人儿的思维导图与王道考研课程&#xff0c;感谢大佬的开源精神&#xff0c;习题来自老师划的重点以及考研真题。此前我尝试了完全使用Python或是结合大语言模型对考研真题进行数据清洗与可视化分析&#xff0c;本人技术…

首发!文心一言插件精品课,共创大模型应用新范式

“AI原生应用要能解决过去解决不了、解决不好的问题&#xff0c;应用才是大模型存在的意义。”越来越多人用AI打造自己的生产力工具、专业领域行业助手、游戏娱乐影音大师……你是否跃跃欲试却无从下手&#xff1f;机会来了&#xff01;《文心一言插件开发课》震撼来袭&#xf…

STM32--系统滴答SysTick

一、SysTick是什么&#xff1f; Systick定时器是一个24bit的倒计时&#xff08;向下计数&#xff09;定时器&#xff0c;功能就是实现简单的延时。 SysTick 是一种系统定时器&#xff0c;通常在嵌入式系统中使用。它是 ARM Cortex-M 处理器的一个特殊定时器&#xff0c;用于提…

基于樽海鞘群算法优化概率神经网络PNN的分类预测 - 附代码

基于樽海鞘群算法优化概率神经网络PNN的分类预测 - 附代码 文章目录 基于樽海鞘群算法优化概率神经网络PNN的分类预测 - 附代码1.PNN网络概述2.变压器故障诊街系统相关背景2.1 模型建立 3.基于樽海鞘群优化的PNN网络5.测试结果6.参考文献7.Matlab代码 摘要&#xff1a;针对PNN神…

微信聊天,收到二维码图片就自动帮你提取出来的方法

10-3 如果你是二维码收集的重度用户&#xff0c;那我非常推荐你好好阅读本文&#xff0c;也许可以帮你解决你的问题&#xff0c;比如做网推的人&#xff0c;需要常年混迹在各种微信群&#xff0c;那如何在各个微信群中收集到群友分享出来的二维码&#xff0c;并且要立即保存出…

Pyside6/PYQT6如何实现无边框设计,解决无边框窗口无法移动的问题

文章目录 💢 问题 💢💯 解决方案 💯🍔 准备工作🐾 操作步骤🐾 窗口无边框🐾 窗口透明🐾 实现窗口可移动⚓️ 相关链接 ⚓️💢 问题 💢 有时候我们需要一个无边框的UI设计来实现/美化一些功能,如:制作一个桌面时钟,进度条展示等,要实现无边框其实很简…

基于springboot实现桥牌计分管理系统项目【项目源码】计算机毕业设计

基于springboot实现桥牌计分管理系统演示 JAVA简介 JavaScript是一种网络脚本语言&#xff0c;广泛运用于web应用开发&#xff0c;可以用来添加网页的格式动态效果&#xff0c;该语言不用进行预编译就直接运行&#xff0c;可以直接嵌入HTML语言中&#xff0c;写成js语言&#…

Liunx命令汇总

一.用户相关命令 1.1账号管理 创建用户&#xff1a; useradd &#xff08;选项&#xff09; 用户名用户口令&#xff1a; passwd &#xff08;选项&#xff09; 用户名修改用户&#xff1a; usermod 选项 用户名删除用户&#xff1a; userdel &#xff08;选项&#xff09; 用…

SpringBootWeb案例——Tlias智能学习辅助系统(3)——登录校验

前一节已经实现了部门管理、员工管理的基本功能。但并没有登录&#xff0c;就直接访问到了Tlias智能学习辅助系统的后台&#xff0c;这节来实现登录认证。 目录 登录功能登录校验(重点)会话技术会话跟踪方案一 Cookie&#xff08;客户端会话跟踪技术&#xff09;会话跟踪方案二…

微信支付服务商消费者投诉及时处理与商户违规及时通知,支持多服务商

大家好&#xff0c;我是小悟 微信直连商户处理消费者投诉的功能解决了很多商户对于投诉处理不及时而导致商户号出现异常的问题&#xff0c;可以说解决了实实在在的问题。 很多小伙伴私信说自己是服务商角色&#xff0c;也需要微信支付服务商处理消费者投诉的功能&#xff0c;…

ablation study

文章目录 ablation study1、消融实验思想是什么&#xff1f;2、消融实验意义3、消融实验应用场景举例 ablation study 1、消融实验思想是什么&#xff1f; “消融实验”&#xff08;ablation study&#xff09;通常指的是通过逐步移除系统的一部分来评估该系统的贡献。这种方法…

分享一下关于“vcruntime140_1.dll丢失的5种解决方法

今天我来给大家分享一下关于“vcruntime140_1.dll丢失的5种修复方法”的分享。首先&#xff0c;我们来了解一下vcruntime140_1.dll丢失的原因。 病毒感染&#xff1a;病毒或恶意软件可能损坏或删除vcruntime140_1.dll文件。 系统更新或软件安装&#xff1a;在进行系统更新或安…

使用.net 构建 Elsa Workflow

对接过蓝凌OA 也基于泛微OA数据库原型重新研发上线过产品&#xff0c;自研的开源的也上线过 每个公司对OA流程引擎介绍 都不一样的&#xff0c; 比如Elsa 这款微软MVP开源组件&#xff0c;基于跨平台开发的技术含量高&#xff0c;专门做OA的同行推过对应文章。 直接看怎么用吧。…

JavaScript逆向之Hook技术

Hook技术&#xff1a; 背景&#xff1a; ​ 在js逆向的过程种&#xff0c;当我们遇到加密参数&#xff0c;可以使用关键字全局搜素&#xff0c;跟栈&#xff0c;还有一种就是hook技术。跟栈就是比较麻烦&#xff0c;需要我们一个个找&#xff0c;hook技术就比较厉害了&#x…

Unity 使用INI文件存储数据或配置参数预设

法1&#xff1a;调用外部Capi库 具体使用&#xff1a; public class Ini{//读取INI文件需要调用C的APP[System.Runtime.InteropServices.DllImport("kernel32")]private static extern long WritePrivateProfileString(string section, string key, string val, st…

【数据结构初阶】顺序表

各位读者老爷好&#xff0c;又见面了哈&#xff01;鼠鼠我呀现在基于C语言浅浅介绍一下数据结构初阶中的顺序表&#xff0c;希望对你有所帮助&#xff01; 目录 1.线性表 2.顺序表 2.1概念即结构 2.2动态顺序表接口的实现 2.2.1定义顺序表 2.2.2初始化 2.2.3销毁 2.2…

kubenetes-容器运行时接口CRI

一、CRI 容器运行时&#xff08;Container Runtime&#xff09;&#xff0c;运行于Kubernetes&#xff08;K8s&#xff09; 集群的每个节点中&#xff0c;负责容器的整个生命周期。其中Docker是目前应用最广的。随着容器云的发展&#xff0c;越来越多的容器运行时涌现。 为了解…