详解MySQL C API 相关接口(大白话就是:MySQL的c语言怎么写)

news/2024/5/19 0:56:47

文章目录

      • 1、C API 官方文档
      • 2、初始化 MYSQL
      • 3、连接 MySQL
        • 设置连接字符集(使得客户端编码方式匹配)
      • 4、下发 mysql 指令
      • 5、获取 mysql 查询结果(保存起来)
        • 获取行与列
        • 遍历存储结果
      • 6、释放 MYSQL\_RES 对象
      • 7、关闭 MySQL 连接
      • 8、总结

1、C API 官方文档

关于C语言连接数据所涉及到的各种数据结构的介绍以及相关函数的使用其实在 MySQL C API 官方文档中已经给出了,我们可以通过它来快速了解并上手 MySQL C API。

image-20231029131432088

image-20231029131530338

2、初始化 MYSQL

要使用 MySQL C语言库,需要先使用 mysql_init 函数完成对 MYSQL 结构体指针的初始化工作。

MYSQL *mysql_init(MYSQL *mysql)
  • 函数返回值:失败返回 NULL。

注意:mysql_init 函数的参数以及返回值都是 MYSQL 指针类型,对于 MYSQL,大家把它类比到C语言中的文件指针来理解即可。MYSQL 和C语言文件 FILE 一样,本质上都是一个结构体。

image-20231029133239373

image-20231029133254539

MYSQL *mfp = mysql_init(nullptr); if(mfp == nullptr) { cerr << "mysql init error" << endl; return 1; } cout << "mysql init success" << endl;

image-20231029140828078

注意:这里用C语言的 NULL 还是C++的 nullptr 都可以,因为它们在数值上都是0;区别在于在定义时 NULL 是一个整数,而 nullptr 则是被强转为了 void* 类型。

3、连接 MySQL

初始化完毕后,我们需要使用 mysql_real_connect 函数来连接数据库。

MYSQL *
mysql_real_connect(MYSQL *mysql,       // MYSQL结构体指针对象const char *host,   // mysqld服务进程所在的主机const char *user,   // 登录MySQL的用户const char *passwd, // 用户密码const char *db,     // 要访问的数据库unsigned int port,  // mysqld服务进程的端口号const char *unix_socket,    // 默认设为NULL即可unsigned long client_flag)  // 默认设为0即可
  • 函数返回值:失败返回0,成功返回传入的MYSQL指针。
#define HOST "127.0.0.1" //MySQL不允许远程访问 出于安全考虑 所以只可以使用本地网络 127.0.0.1
#define USER "li_zheng_yang"
#define PASS "Gaopengyan99999."
#define DBNAME "Five_in_a_row"
#define PORT 3306 //这是系统API接口默认的
if( mysql_real_connect(mysql,HOST,USER,PASS,DBNAME,PORT,NULL,0)==nullptr )//第一个参数叫句柄{cout << "connect failed" << endl;cout << mysql_error(mysql);//放入句柄 查看连接失败原因mysql_close(mysql);return -1;}

image-20231029140931672

设置连接字符集(使得客户端编码方式匹配)

需要注意的是,我们之前在创建数据库时默认使用的字符集是 utf8,而C语言连接数据时默认的字符集是 latin1 的(拉丁),这就会导致我们在向表中插入中文数据时,由于字符集不匹配,最终数据库中存储的数据显式出来是乱码。

所以,我们需要使用 mysql_set_character_set 函数设置连接字符集为 utf8

int mysql_set_character_set(MYSQL *mysql, const char *csname)
  • 函数返回值:返回0表示成功,非0表示失败。
int n = mysql_set_character_set(mfp, "utf8");
if(n != 0) { cout << "warning: character set fail" << endl; }

4、下发 mysql 指令

在成功连接到数据库之后,我们就可以通过 mysql_query 函数来下发 mysql 指令了。

int mysql_query(MYSQL *mysql, const char *stmt_str)
  • 函数返回值:执行成功返回0,失败返回非0。
	//增删改查 int mysql_query(MYSQL *mysql, const char *stmt_str) 这里的第二个参数前面必须加上 constconst char* sql="insert stu values(null,'lzy',21,100,100,100);";//const char* sql="update stu set ch=ch-1 where sn=1;";//const char* sql="delete from stu where sn=1;";int ret=mysql_query(mysql,sql);

需要注意的是,我们在使用 mysql client 时,一条 sql 语句需要以分号结尾;但是在C语言中,sql 语句可以不用带分号,当然带上也没事。

检验是否插入成功:

select* from stu;

image-20240425213855738

检验是否修改成功:

image-20240425214241180

5、获取 mysql 查询结果(保存起来)

我们上面是对数据库执行增删改操作,它们相对来说比较简单,因为我们只需要将指令下发给数据库即可,后面的事情我们不必关心。但==如果我们执行的是查询操作,则需要通过 mysql_store_result 函数来获取查询结果==。

MYSQL_RES *mysql_store_result(MYSQL *mysql)
  • 函数返回值:失败返回 NULL,成功返回一个非空的 MYSQL_RES 类型的结构体指针。

实际上,mysql_store_result 函数会调用 MYSQL 结构体变量中的 st_mysql_methods 字段中的 read_rows 函数指针来获取查询的结果;然后将查询结果保存到 MYSQL_RES 结构体中并返回结构体指针。这样,当执行完 mysql_store_result 以后,其实数据都已经在MYSQL_RES 变量中了,我们直接从中获取即可。

需要注意的是,MYSQL_RES 是通过 malloc/new 空间的方式来保存查询结果的,所以当我们使用完毕之后,一定要记得释放 MYSQL_RES 对象,否则就会造成内存泄漏。同时,MYSQL_RES 结构体中存在查询结果的列数、列信息、行数、行内容等属性,我们需要使用对应的函数来获取这些信息。

image-20231029152423987

获取行与列

unsigned int mysql_num_rows(MYSQL_RES *result)

unsigned int mysql_num_fields(MYSQL_RES *result)
遍历存储结果
for(int i=0;i<num_row;i++){//MYSQL_ROW mysql_fetch_row(MYSQL_RES *result)MYSQL_ROW row=mysql_fetch_row(res);for(int i=0;i<num_col;i++){cout << row[i] << "\t";}cout << endl;}

当然,我们也可以通过调用 mysql_fetch_fields 函数一次获取到所有列的属性信息,然后分别打印。

MYSQL_FIELD *mysql_fetch_fields(MYSQL_RES *res);
  • 获取结果行数。
my_ulonglong mysql_num_rows(MYSQL_RES *result)

6、释放 MYSQL_RES 对象

由于 MYSQL_RES 保存查询结果的空间是通过 malloc/new 得到的,所以当我们使用完毕后需要释放掉 MYSQL_RES 对象,防止内存泄露。

void mysql_free_result(MYSQL_RES *result)
mysql_free_result(res);

7、关闭 MySQL 连接

最后,当我们使用完 MySQL 后,需要关闭 MySQL 之前建立的连接。

void mysql_close(MYSQL *sock);
mysql_close(mfp);

8、总结

使用 MySQL C API 连接数据库进行简单操作的步骤如下:

  1. 初始化 MYSQL 结构体指针 – mysql_init。
  2. 连接 MySQL – mysql_real_connect:需要指定数据库服务所在主机、端口以及登录mysql的用户和密码等信息。
  3. 下发 MySQL 指令 – mysql_query。
  4. 获取 MySQL 查询结果:将查询结果转储到 MYSQL_RES 中 – mysql_store_result,获取查询结果的行数 – mysql_num_rows,获取查询结果列数 – mysql_num_fields,获取单个/所有列字段的 MYSQL_FIELD 属性信息 – mysql_fetch_field/mysql_fetch_fields,获取查询结果单行的内容 (不包含属性行) – mysql_fetch_row。
  5. 释放 MYSQL_RES 对象 – mysql_free_result。
  6. 关闭 MySQL 连接 – mysql_close。
#include<bits/stdc++.h>
#include<mysql/mysql.h>
using namespace std;
#define HOST "127.0.0.1" //MySQL不允许远程访问 出于安全考虑 所以只可以使用本地网络 127.0.0.1
#define USER "root"
#define PASS "Gaopengyan99999."
#define DBNAME "Five_in_a_row"
#define PORT 3306 //这是系统API接口默认的
int main()
{1.初始化MySQL句柄MYSQL* mysql = mysql_init(nullptr);//MYSQL *mysql_init(MYSQL *mysql) 传空 那么就是堆上申请空间//MYSQL 和C语言文件 FILE 一样,本质上都是一个结构体 所以mysql就相当于是结构体创建的节点 //类似于 ListNode* nodeif(mysql==nullptr){cout << "create fail" << endl;return -1;}/2.连接服务器/*MYSQL * mysql_real_connect(MYSQL *mysql,       // MYSQL结构体指针对象const char *host,   // mysqld服务进程所在的主机const char *user,   // 登录MySQL的用户const char *passwd, // 用户密码const char *db,     // 要访问的数据库unsigned int port,  // mysqld服务进程的端口号const char *unix_socket,    // 默认设为NULL即可unsigned long client_flag)  // 默认设为0即可*/if( mysql_real_connect(mysql,HOST,USER,PASS,DBNAME,PORT,NULL,0)==nullptr )//第一个参数叫句柄{cout << "connect failed" << endl;cout << mysql_error(mysql);//放入句柄 查看连接失败原因mysql_close(mysql);return -1;}/3.设置客户端字符集///if( mysql_set_character_set(mysql,"utf8") != 0 ) //文档规定 为0则为成功 非0则失败了{cout << "set character failed" << endl;cout << mysql_error(mysql);//放入句柄 查看连接失败原因mysql_close(mysql);return -1;}/4.选择要操作的数据库///这一步不需要进行了 我们在连接服务器的时候实则已经默认选择过了//mysql_select_db(mysql,DBNAME);//5.执行sql语句////增删改查 int mysql_query(MYSQL *mysql, const char *stmt_str) 这里的第二个参数前面必须加上 const//const char* sql="insert stu values(null,'lzy',21,100,100,100);";//const char* sql="update stu set ch=ch-1 where sn=1;";//const char* sql="delete from stu where sn=1;";const char* sql="select * from stu;";int ret=mysql_query(mysql,sql);if( ret!=0 )//查询和增删改不一样 得保存数据到本地{cout << "find failed" << endl;cout << mysql_error(mysql);//放入句柄 查看连接失败原因mysql_close(mysql);return -1;}///6.select保存结构到本地/MYSQL_RES *res=mysql_store_result(mysql);if( res == nullptr){mysql_close(mysql);return -1;}//7.获取行数与列数//unsigned int mysql_num_fields(MYSQL_RES *result)//unsigned int mysql_num_rows(MYSQL_RES *result)int num_row=mysql_num_rows(res);//res是上面用mysql_store_result获取出来保存进去的结果int num_col=mysql_num_fields(res);//8.遍历读取数据for(int i=0;i<num_row;i++){//MYSQL_ROW mysql_fetch_row(MYSQL_RES *result)MYSQL_ROW row=mysql_fetch_row(res);for(int i=0;i<num_col;i++){cout << row[i] << "\t";}cout << endl;}//9.释放结果集///mysql_free_result(res);/10.关闭连接/mysql_close(mysql);
}


http://www.mrgr.cn/p/48561127

相关文章

vue3 删除对象中的属性,可以使用js里的delete,但需注意ts定义对象类型!

如上如&#xff0c;当使用delete 删除stateData中的属性时&#xff0c; 报错&#xff0c;意思为 TypeScript 错误“‘delete’ 运算符的操作数必须是可选的 什么原因呢&#xff1f;是因为我偷懒 缺少了ts定义类型 方法一&#xff1a; &#xff08;不推荐&#xff09; delete …

嵌入式笔记4.1 GPIO 功能复用

目录一、了解 MCU(GPIO)具有的所有复用功能通过查看 MCU 的数据手册可以知道 MCU 的所有引脚的功能:例 STM32L431:例 stm32f103:复用、重映射、多路复用(多功能引脚)GPIO复用(AF - Alternate Function)重映射(Remapping)多路复用(Multi-function)常见引脚功能一览…

【八股】Redisson分布式锁

Redisson分布式锁 主要了解了Redisson分布式锁实现的三个功能&#xff1a; 1.可重入 -> 防止死锁 2.可重试&#xff08;i.e. 非阻塞获取锁&#xff09; 3.自动续约 1. 可重入 原理&#xff1a; 利用Redis的Hash结构&#xff0c;记录了使用当前锁的线程id和重用次数&#…

如何分析和优化慢sql语句

前言 sql查询速度比较慢容易成为性能瓶颈,这时我们可以优化我们的sql语句或数据库表 一般sql语句执行很慢的种类分为: 1.聚合查询 2.多表查询 3.表数据量过大查询 4.深度分页查询 这四种的前三种都可以通过优化sql语句来优化sql查询速度 正文 聚合查询 我们可以通过尝…

初始C++

1. C关键字(C98) C总计63个关键字&#xff0c; C语言32个关键字 ps&#xff1a;下面我们只是看一下C有多少关键字&#xff0c;不对关键字进行具体的讲解。后面我们学到以后再 细讲。 2. 命名空间 在C/C中&#xff0c;变量、函数和后面要学到的类都是大量存在的&#xff0c;…

ps/lr如何为一个型号相机的raw使用其他相机的预设

首先单独下载camera raw,进到C:\ProgramData\Adobe\CameraRaw\CameraProfiles\Camera中获取想要的相机型号的预设dcp文件 去 https://liquidtelecom.dl.sourceforge.net/project/dcptool/dcptool/dcpTool V1.11.0/dcpTool_1_11_0.zip?viasf=1 下载dcp编译工具dcpTool cd C:\U…

Oracle 21 C 安装详细操作手册,并配置客户端连接

Oracle 21 C 安装详细操作手册 Win 11 Oracle 21C 下载&#xff1a; Database Software Downloads | Oracle 中国 云盘共享 链接&#xff1a;https://pan.baidu.com/s/12XCilnFYyLFnSVoU_ShaSA 提取码&#xff1a;nfwc Oracle 21C 配置与登陆&#xff1a; 开始菜单 NetMa…

一文速览Llama 3及其微调:如何通过paper-review数据集微调Llama3 8B

前言 4.19日凌晨正准备睡觉时&#xff0c;突然审稿项目组的文弱同学说&#xff1a;Meta发布Llama 3系列大语言模型了 一查&#xff0c;还真是 本文以大模型开发者的视角&#xff0c;基于Meta官方博客的介绍&#xff1a;Introducing Meta Llama 3: The most capable openly a…

记录收集博客园美化代码

记录了一些好看实用的博客园美化主题🌃 初始微改版预览页面点击查看代码 /* 全局字体设定 */ #cnblogs_post_body {font-family: Roboto, sans-serif;color: #333; /* 增强字体颜色对比度,提高可读性 */ }/* 一级标题 */ #cnblogs_post_body h1 {font-size: 30px;font-weigh…

spring-boot学习记录

💭 记录spring-boot学习过程🕐 学习参考网站 1天搞定SpringBoot+Vue全栈开发-bilibili🕐 准备 🕑 项目热部署 视频中的idea版本较老,热部署实现参考IDEA2021 热部署-知乎 🕑 修改默认端口 在 src/main/resources/application.properties 文件中添加 server.port=80�…

Python学习从0开始——项目一day02数据库连接

Python学习从0开始——项目一day02数据库连接 一、在线云数据库二、测试数据库连接三、数据库驱动介绍四、SQL执行4.1插入测试数据4.2安装数据库连接模块4.3测试SQL语句执行4.4执行SQL的固定步骤及示例 一、在线云数据库 找了一个在线数据库&#xff0c;需要邮箱注册&#xff…

C语言结课实战项目_贪吃蛇小游戏

✨✨所属专栏&#xff1a;C语言✨✨ ✨✨作者主页&#xff1a;嶔某✨✨ 游戏源代码链接&#xff1a;function/贪吃蛇 钦某/c-language-learning - 码云 - 开源中国 (gitee.com) 最终实现效果&#xff1a; 实现基本的功能&#xff1a; void set_pos(short x, short y);//定位光…

需求 分析

需求分析的任务 需求分析的任务 1、需求分析是软件定义时期的最后一个阶段&#xff0c;它的基本任务是准确地回答“系统必须做什么?”这个问题。 2、确定系统必须完成哪些工作&#xff0c;也就是对目标系统提出完整、准确、清晰、具体的要求。 3、系统分析员应该写出软件需求…

世强硬创获昕感科技授权代理,SiC MOSFET实现超低导通电阻

近日&#xff0c;世强先进&#xff08;深圳&#xff09;科技股份有限公司&#xff08;下称“世强先进”&#xff09;获北京昕感科技有限责任公司&#xff08;下称“昕感科技”&#xff0c;英文名&#xff1a;NEXIC&#xff09;授权代理&#xff0c;为光伏、储能、电网、新能源汽…

一文搞懂“对账系统”

对于每天都需要对账的生意来讲,如果遇上大的额数,就会出现困难,为了提升核对效率以及准确性,对账系统有一定的改变是避免不了的,下面是笔者整理的关于“对账系统”的内容分享,想要了解相关内容的可以接着继续往下了解了解哦!账目核算是财务工作的必要部分,随着线上交易…

UE4纯C++实现游戏快捷栏之将快捷栏注册到玩家状态

我们有了UI有了物品信息,接下来我们便需要给每一个玩家绑定一个快捷栏了,我们分以下几部分来实现我们玩家的快捷栏。1.Types.h struct ShortcutContainer:我们定义快捷栏的单个容器结构体,其内部存储玩家所引用的快捷栏的单个格子的信息数据基础的,我们将在结构体中保存{单…

个人博客系统的设计与实现

https://download.csdn.net/download/liuhaikang/89222885http://点击下载源码和论文 本 科 毕 业 设 计&#xff08;论文&#xff09; 题 目&#xff1a;个人博客系统的设计与实现 专题题目&#xff1a; 本 科 毕 业 设 计&#xff08;论文&#xff09;任 务 书 题 …

buuctf-pwn-1.test_your_nc

简单题,知道nc怎么用就好 基本用法 nc 地址 端口号 地址可以是一个域名,也可以是ip地址,地址和端口中间不是:,而是一个空格 连接上之后直接ls就看到flag文件了,cat flag查看flag文件的内容获取flag 注意windows上的nc需要下载,linux上一般会自带flag{c41a6f35-bb45-4c01…

十六进制转换

十进制转换为十六进制——利用栈的“先进后出”的思想 题目:设计一个进制转换程序,使用顺序栈设计一个把十进制数转换为十六进制数的接口,实现当通过键盘输入一个非负的十进制数,可以在终端输出对应的十六进制数。 思路: 1.输入一个十进制数num 2.定义一个链表 3.将余数(…

【Python数据库】Redis

文章目录 [toc]数据插入数据查询数据更新数据删除查询存在的所有key 个人主页&#xff1a;丷从心 系列专栏&#xff1a;Python数据库 学习指南&#xff1a;Python学习指南 数据插入 from redis import Redisdef insert_data():redis_cli Redis(hostlocalhost, port6379, db…