C中Mysql的基本api接口
- 一、初始化
- 参数
- 返回值
- 二、链接服务器
- 三、执行SQL语句
- 注意事项
- 四、获取结果集
- 4.1mysql_affected_rows和mysql_num_rows
- 4.2mysql_store_result与mysql_free_result
- 注意事项
- 注意事项
- 整体的工作流程
- 4.3mysql_use_result()
- 4.4mysql_field_count()
- 五、关闭MySQL
- 使用和区别
- 六、错误处理
- mysql_errno()` 和 `mysql_error()
一、初始化
创建MYSQL* 对象,使用mysql_init函数
MYSQL * mysql;
mysql_init(mysql);
参数
mysql:指向一个MYSQL结构的指针。通常传递NULL,系统将自动为您分配和初始化一个新的MYSQL对象。
返回值
- 成功:返回一个指向
MYSQL结构的指针。 - 失败:返回
NULL。
二、链接服务器
使用函数mysql_real_connect();
MYSQL *mysql_real_connect(MYSQL *mysql, // mysql_init() 函数的返回值const char *host, // mysql服务器的主机地址, 写IP地址即可// localhost, null -> 代表本地连接const char *user, // 连接mysql服务器的用户名, 默认: root const char *passwd, // 连接mysql服务器用户对应的密码, root用户的密码const char *db, // 要使用的数据库的名字unsigned int port, // 连接的mysql服务器监听的端口// 如果==0, 使用mysql的默认端口3306, !=0, 使用指定的这个端口const char *unix_socket,// 本地套接字, 通常在 Windows 上使用命名管道,而在 Unix/Linux 系统上使用 Unix 套接字。如果不使用这类连接方式,此参数应设为 NULL。unsigned long client_flag); //连接时使用的特定客户端标志 通常指定为0
)
返回值:
- 成功:返回一个指向 MYSQL 结构的指针(通常是传入的那个指针)。
- 失败:返回 NULL,并且可以通过
mysql_error函数来获取错误信息。
三、执行SQL语句
// 执行一个sql语句, 添删查改的sql语句都可以
int mysql_query(MYSQL *mysql, const char *query);
参数:- mysql: mysql_real_connect() 的返回值- query: 一个可以执行的sql语句, 结尾的位置不需要加 ;
返回值: - 如果查询成功,返回0。如果是查询, 结果集在mysql 对象中- 如果出现错误,返回非0值。
注意事项
- 资源管理:使用
mysql_query后,如果查询是 SELECT 类型的,你通常需要调用mysql_store_result或mysql_use_result来处理返回的数据。记得在不需要结果集时使用mysql_free_result来释放内存。- 错误处理:在生产环境中,每次调用
mysql_query后都应检查返回值,并适当处理错误。这样可以避免程序在错误状态下继续执行,导致更复杂的问题。- 安全性:避免将未经验证的用户输入直接用于 SQL 语句,以防止 SQL 注入攻击。考虑使用预处理语句和参数化查询来提高安全性。
这些基本的使用方式和注意事项可以帮助你有效地使用
mysql_query来执行数据库操作。
值得注意的是在 MySQL 中,SQL 语句的关键字(如 SELECT, INSERT, UPDATE, DELETE 等)通常是不区分大小写的,这意味着 “select” 和 “SELECT” 在 MySQL 解释器看来是相同的。然而,数据库名称、表名、列名的大小写敏感性则取决于操作系统的文件系统和 MySQL 的配置。在 Unix、Linux 系统中,它们默认是大小写敏感的,而在 Windows 系统中默认是不敏感的。
mysql_query实质上是在客户端和 MySQL 服务器之间进行网络通信的一个接口。在使用 TCP/IP 协议的情况下,客户端通过网络向服务器发送请求,并接收服务器的响应。这个过程涉及到网络数据的发送和接收,是基于客户端-服务器模型的典型应用。
要注意的是标准 SQL 查询:如果你的查询是简单的文本,不包含二进制数据,且不需要在 SQL 语句中嵌入 null 字符,使用 mysql_query 就足够了。
而当数据中有二进制数据就需要使用mysql_real_query
int mysql_real_query(MYSQL *mysql, const char *query, unsigned long length);
- 灵活性:可以执行包含 null 字符的查询,因为它要求用户明确提供查询的长度。
- 手动指定长度:用户必须指定查询字符串的长度,这允许函数处理二进制数据或包含 null 字符的数据。
- 适用场景:非常适合执行包含 BLOB 类型数据的 SQL 语句。
四、获取结果集
4.1mysql_affected_rows和mysql_num_rows
uint64_t mysql_affected_rows(MYSQL *mysql)
mysql_affected_rows() 可能是 在使用 mysql_real_query() 或 mysql_query() 执行语句后立即调用。它返回 上一个更改、删除或插入的行数 语句(如果是 UPDATE、DELETE 或 INSERT)。对于 SELECT 语mysql_affected_rows() 有效 像 mysql_num_rows()。
对于 UPDATE 语句, 默认情况下,affected-rows 值是实际的行数 改变。如果在以下情况下指定 mysql_real_connect() 的标志 连接到 mysqld,受影响的行 value 是“找到”的行数;那是 与子句匹配。CLIENT_FOUND_ROWSWHERE
对于 REPLACE 语句, 如果新行替换了旧行,则 affected-rows 值为 2, 因为在这种情况下,在重复项之后插入了一行 已删除。
uint64_t mysql_num_rows(MYSQL_RES *result)
返回结果集中的行数。
4.2mysql_store_result与mysql_free_result
MYSQL_RES *mysql_store_result(MYSQL *mysql);
参数说明
mysql: 指向 MYSQL 结构的指针,该结构体应已通过 mysql_real_connect 函数建立了与 MySQL 服务器的连接,并已成功执行了一个查询(如通过 mysql_query)。
返回值
成功: 返回一个指向 MYSQL_RES 结构的指针,这个结构包含了从服务器返回的所有结果数据。
失败 或 查询没有产生结果集(例如执行的是 UPDATE 或 DELETE 语句): 返回 NULL。
如何将行和列的数据从结果集中取出, 需要使用其他函数
注:mysql_store_result 函数只会返回与最近一次通过 mysql_query (或其他发送 SQL 语句的函数)执行的查询相关的结果。它不会存储或回溯到之前的查询结果,而是专注于最后执行的查询。
注意事项
- 内存管理:使用
mysql_store_result后,必须在不再需要结果集时调用mysql_free_result来释放内存。- 性能考量:由于
mysql_store_result会将所有结果数据存储在客户端内存中,对于返回大量数据的查询,这可能会消耗大量内存和网络资源。如果处理大型数据集,可能需要考虑使用mysql_use_result,该函数允许逐行检索数据,从而减少内存占用。- 错误处理:始终检查
mysql_store_result的返回值,并使用mysql_error函数来诊断错误。通过
mysql_store_result,你可以方便地在客户端处理来自 MySQL 服务器的数据,但务必注意资源管理和错误处理,以确保应用程序的稳定性和效率。
void mysql_free_result(MYSQL_RES *result);
参数说明
result: 指向 MYSQL_RES 结构的指针,该结构包含了之前查询的结果集。
mysql_free_result 函数是 MySQL C API 中用来释放由 mysql_store_result 或 mysql_use_result 函数分配的结果集内存的函数。这是清理和资源管理的重要一步,确保在查询处理完成后不会造成内存泄漏。
当使用 mysql_store_result 或 mysql_use_result 从 MySQL 服务器获取查询结果后,相关的数据会被存储在 MYSQL_RES 结构中。这个结构占用一定的内存空间,当数据处理完毕后,应该使用 mysql_free_result 来释放这些内存。如果不这样做,每次查询后未释放的内存会累积,最终可能导致内存不足或程序崩溃。
实际使用
#include <mysql.h>
#include <iostream>int main() {MYSQL *conn;MYSQL_RES *res;MYSQL_ROW row;conn = mysql_init(NULL);if (!conn) {std::cerr << "MySQL initialization failed." << std::endl;return 1;}if (!mysql_real_connect(conn, "localhost", "user", "password", "database", 0, NULL, 0)) {std::cerr << "Failed to connect to database: " << mysql_error(conn) << std::endl;mysql_close(conn);return 1;}if (mysql_query(conn, "SELECT id, name FROM users")) {std::cerr << "Query failed: " << mysql_error(conn) << std::endl;mysql_close(conn);return 1;}res = mysql_store_result(conn);if (!res) {std::cerr << "Failed to retrieve result set: " << mysql_error(conn) << std::endl;mysql_close(conn);return 1;}while ((row = mysql_fetch_row(res))) {std::cout << "ID: " << row[0] << ", Name: " << row[1] << std::endl;}// After processing the results, free the memory.mysql_free_result(res);mysql_close(conn);return 0;
}
注意事项
- 只释放一次:确保对每个
MYSQL_RES结构只调用一次mysql_free_result。重复释放可能会导致未定义行为或程序崩溃。- 适时释放:尽可能在数据处理完毕后立即释放结果集,特别是在处理多个查询的情况下,避免不必要的内存占用。
- 检查
NULL:如果mysql_store_result或mysql_use_result返回NULL,表明没有结果集需要处理,因此不应该调用mysql_free_result
整体的工作流程
- 执行查询:首先使用
mysql_query执行一个 SQL 查询。- 检索结果:使用
mysql_store_result检索查询结果并存储在MYSQL_RES *结构中。- 处理数据:通过循环等方式处理这些结果。
- 释放资源:使用
mysql_free_result释放MYSQL_RES *结构占用的内存。- 重复操作:如果需要再次查询,回到第一步,执行新的
mysql_query,然后使用mysql_store_result检索新的结果。
值得注意的是如果你在调用 mysql_store_result 之后没有使用 mysql_free_result 来释放结果集的内存,然后再次进行查询并调用 mysql_store_result,这将导致内存泄漏。这是因为每次调用 mysql_store_result 都会从 MySQL 服务器获取新的结果数据,并在客户端为这些数据分配新的内存。如果旧的结果集没有被适当释放,那么这部分内存仍然被占用,尽管你已经无法再访问到这部分数据。
4.3mysql_use_result()
MYSQL_RES *mysql_use_result(MYSQL *mysql)
参数说明
mysql: 指向 MYSQL 结构的指针,该结构表示一个已连接的 MySQL 数据库。
返回值
成功:返回一个指向 MYSQL_RES 结构的指针,该结构代表结果集。
失败:返回 NULL,并且可以通过 mysql_error 函数获取错误信息。
while ((row = mysql_fetch_row(res))) {std::cout << "ID: " << row[0] << ", Name: " << row[1] << std::endl;
}
- 逐行处理:
mysql_use_result逐行读取结果集,这意味着你不能在获取完整结果集之前执行其他查询,否则会导致未定义行为。- 资源释放:使用
mysql_use_result后,一定要调用mysql_free_result释放结果集,确保内存资源被适当管理。- 网络延迟:因为
mysql_use_result逐行读取数据,受网络延迟的影响可能会比mysql_store_result慢,但对于大结果集它能显著降低内存占用。
mysql_use_result 与 mysql_store_result 都是用来处理查询结果集的函数,但它们在处理方式上有以下区别:
mysql_store_result:一次性将整个结果集从服务器读取到客户端内存中,适用于结果集较小的情况,因为它会在客户端占用较多内存。mysql_use_result:逐行从服务器读取结果集,适用于结果集较大的情况,因为它不会将整个结果集一次性加载到内存中,节省了内存占用。
4.4mysql_field_count()
在第三部分我们看到mysql_query不仅可以使用SELECT SQL语句还可以使用INSERT语句,我们对于查询语句的列数和是否是查询语句是有一定的判断需求的
unsigned int mysql_field_count(MYSQL *mysql)
- 返回一个
unsigned int值,表示最近执行的查询返回的列数。如果没有活动的查询或查询没有返回任何结果,则返回 0。
注意事项
- 正确的上下文:
mysql_field_count应该在成功执行查询之后调用,以确保它返回正确的列数。如果在没有活动查询的情况下调用它,返回值将是 0。- 结果集处理:当你使用
mysql_store_result或mysql_use_result来获取结果集时,使用mysql_field_count可以帮助你动态地处理结果集中的数据。- 查询类型:对于不返回结果集的查询(如
INSERT、UPDATE、DELETE),mysql_field_count返回 0。
五、关闭MySQL
void mysql_close(MYSQL *mysql)
当你完成了数据库操作并不再需要与数据库的连接时,应该调用 mysql_close 来关闭连接。这个调用确保所有的客户端资源被适当清理,包括内部缓冲区和连接句柄。如果不关闭连接,可能会导致资源泄漏。
void mysql_library_end(void);
在所有数据库连接都已通过 mysql_close 关闭后,应调用 mysql_library_end 来清理 MySQL 客户端库使用的所有资源。这个函数主要用于多线程环境中,在所有线程都完成数据库操作并关闭连接后,由主线程调用以确保所有的客户端库资源被正确释放。
使用和区别
使用场景:
mysql_close用于关闭单个数据库连接;mysql_library_end用于在程序结束前清理客户端库。调用时机:
mysql_close:每个数据库连接在不再需要时应该被关闭。
mysql_library_end:在程序结束,所有数据库连接都已关闭后调用。
值得注意的是即使在单线程应用程序中,依然推荐在程序结束时调用 mysql_library_end。这个函数的作用不仅限于多线程环境,它负责清理 MySQL 客户端库使用的全局资源,确保所有初始化时分配的资源被适当释放,这包括内部数据结构、缓冲区等。
六、错误处理
mysql_errno()和mysql_error()
mysql_errno() 返回最近一次 MySQL 函数调用所产生的错误代码。这个错误代码是一个整数值,表示特定类型的错误。
unsigned int mysql_errno(MYSQL *mysql);
返回一个 `unsigned int` 类型的错误代码。如果没有错误发生,返回值为 `0`。
mysql_error() 返回最近一次 MySQL 函数调用所产生的错误信息字符串。这个字符串描述了具体的错误情况,通常比错误代码更易读和理解。
const char *mysql_error(MYSQL *mysql);
返回一个指向描述错误的字符串的指针。如果没有错误发生,返回一个空字符串。
通过使用 mysql_errno() 和 mysql_error(),你可以更详细地了解数据库操作中的错误,帮助调试和改进程序的错误处理能力。这两个函数在处理复杂数据库交互时尤为重要,因为它们可以提供具体的错误信息和错误代码,有助于定位和解决问题。
相关文章:
C中Mysql的基本api接口
一、初始化参数返回值 二、链接服务器三、执行SQL语句注意事项 四、获取结果集4.1mysql_affected_rows和mysql_num_rows4.2mysql_store_result与mysql_free_result注意事项注意事项整体的工作流程 4.3mysql_use_result()4.4mysql_field_count(…...
grafana10.x报错 Failed to upgrade legacy queries Datasource x was not found
问题 grafana 从6.x升级到10.x后,导入json文件后报错,数据源x查询不到,grafana不显示数据; Templating Failed to upgrade legacy queries Datasource x was not found解决方法 可能grafana升级后数据源找不到,在面板…...
项目管理-案例重点知识(干系人管理)
项目管理:每天进步一点点~ 活到老,学到老 ヾ(◍∇◍)ノ゙ 何时学习都不晚,加油 四、干系人管理 案例重点知识 干系人管理 案例 重点内容: (1)权力利益方格、权力影响方格ÿ…...
微信小程序踩坑,skyline模式下,scroll-view下面的一级元素设置margin中的auto无效,具体数据有效
开发工具版本 基础库 开启skyline渲染调试 问题描述 skyline模式下,scroll-view下面的一级元素的margin写auto的值是没有效果的(二级元素margin写auto是有效果的),关闭这个模式就正常显示 演示效果图 父元素的宽度和高度效果(宽度是750rpx,宽度占满的) 一级元素宽度和css效果…...
jspXMl标记语言基础
1.打开命令框进入数据库 打开eclipse创建需要连接的项目 粘贴驱动程序 查看驱动器 使用sql的包 int代表个 conlm代表列名 <%page import"java.sql.ResultSet"%> <%page import"java.sql.Statement"%> <%page import"java.sql.Connect…...
【DevOps】Linux 与虚拟局域网 (VLAN) 详解
目录 一、什么是VLAN? 二、VLAN的工作原理 三、Linux中的VLAN支持 四、内核模块 五、用户空间工具 六、创建VLAN 七、配置VLAN 八、管理VLAN 九、VLAN的应用 1、 网络隔离 2、网络管理 3、网络扩展 十、VLAN的优点和限制 十一、结论 虚拟局域网&#…...
《表格新视界:从罗列到洞察的飞跃》
在信息爆炸的当下,表格宛如一位低调的英雄,默默支撑着无数的数据世界。 曾经,我们只把表格当作简单的记录工具,一行行、一列列地填着数字与文字。但如今,表格已华丽转身,成为了展现数据魅力的舞台。 它不…...
风电功率预测 | 基于GRU门控循环单元的风电功率预测(附matlab完整源码)
风电功率预测 风电功率预测 | 基于GRU门控循环单元的风电功率预测(附matlab完整源码)完整代码风电功率预测 | 基于GRU门控循环单元的风电功率预测(附matlab完整源码) 完整代码 clc; clear close allX = xlsread(风电场预测.xlsx)...
0基础安装 composer
解决: composer 不是内部或外部命令,也不是可运行的程序 或批处理文件。 php composer.phar可以运行 安装环境:系统w11 官网地址:Composer 1.安装composer 1.1打开命令行窗口 在命令行窗口里,右键是粘贴࿰…...
MYSQL-9.问题排查
问题排查的思路与方向 问题排查思路 分析问题:根据理论知识经验分析问题,判断问题可能出现的位置或可能引起问题的原因,将目标缩小到一定范围;排查问题:基于上一步的结果,从引发问题的“可疑性”角度出发…...
制造企业数据管理:从数据到价值的转化
在数字化浪潮席卷全球的今天,制造企业面临着前所未有的机遇与挑战。如何从海量的数据中提取有价值的信息,将其转化为企业的核心竞争力,成为了每一个制造企业必须面对的问题。而数据管理,正是实现这一转化的关键所在。制造企业数据…...
单例模式介绍
【一】为什么要单例模式 单例设计模式: 一个类只允许创建一个对象(或者实例),那这个类就是一个单例类,这种设计模式就叫作单例设计模式,简称单例模式。 当一个类的功能比较单一,只需要一个实例…...
Facebook企业户/在Facebook上做推广有什么好处?
想到出海,必会想到Facebook作为世界上最大的社交网络,Facebook拥有难以想象的用户数量,流量大到没朋友。近年来也是独立站卖家获取流量的有力工具之一。独立站卖家在Facebook上做广告的好处? Facebook,Google 开企业广…...
Go GORM实战(二) | 数据库连接的N种方式
连接数据库 使用GORM连接数据库还是比较简单的,概括起来就是以下三个步骤: 引入gorm.io/gorm和对应数据库的驱动库,如gorm.io/driver/sqlite。 调用对应驱动库的Open()或New()函数返回一个实现了gorm.Dialector接口的实例。 调用gorm.Open…...
Cocos Creator 2D Mask与Layout 使用详解
Cocos Creator是一款强大的2D游戏开发引擎,提供了丰富的功能和工具,使开发者可以轻松创建出高质量的游戏。其中,2D Mask和Layout是Cocos Creator中常用的两个组件,它们可以帮助开发者实现更加复杂和精美的游戏界面设计。本文将详细…...
项目-坦克大战
增加功能 我方坦克在发射的子弹消亡后,才能发射新的子弹。同时实现发多颗子弹 1,在按下J键,我们判断当前hero对象的子弹,是否已经销毁2,如果没有销毁,就不去触发shotEnemyTank3,如果已经销毁&…...
代码随想录算法训练营第二十九天| LeetCode491.递增子序列* 、LeetCode46.全排列*、LeetCode47.全排列 II
#LeetCode 491. Non-decreasing Subsequences #LeetCode 491. 视频讲解:回溯算法精讲,树层去重与树枝去重 | LeetCode:491.递增子序列_哔哩哔哩_bilibili 首先,本题不能考虑首先对数组排序,排序会导致数组直接变为一个…...
基于SpringBoot设计模式之开端
文章目录 前言引言开始 前言 为了更好的在项目中,能更加优雅的使用设计模式,比较针对性的解决我们的问题。我将在这个专栏详细的描述23种设计模式,为了与时俱进,我打算通过springboot的形式将23种设计模式全部撸完! 引…...
tensorflow实现二分类
# 导入所需库和模块 from tensorflow.keras.layers import Dense, Input, Activation # 导入神经网络层和激活函数模块 from tensorflow.keras.models import Sequential # 导入Keras的Sequential模型 import pandas as pd # 导入Pandas库用于数据处理 import numpy as np …...
简化路径[中等]
优质博文:IT-BLOG-CN 一、题目 给你一个字符串path,表示指向某一文件或目录的Unix风格 绝对路径 (以/开头),请你将其转化为更加简洁的规范路径。在Unix风格的文件系统中,一个点.表示当前目录本身&#x…...
【Axure高保真原型】引导弹窗
今天和大家中分享引导弹窗的原型模板,载入页面后,会显示引导弹窗,适用于引导用户使用页面,点击完成后,会显示下一个引导弹窗,直至最后一个引导弹窗完成后进入首页。具体效果可以点击下方视频观看或打开下方…...
【ROS】Nav2源码之nav2_behavior_tree-行为树节点列表
1、行为树节点分类 在 Nav2(Navigation2)的行为树框架中,行为树节点插件按照功能分为 Action(动作节点)、Condition(条件节点)、Control(控制节点) 和 Decorator(装饰节点) 四类。 1.1 动作节点 Action 执行具体的机器人操作或任务,直接与硬件、传感器或外部系统…...
面试高频问题
文章目录 🚀 消息队列核心技术揭秘:从入门到秒杀面试官1️⃣ Kafka为何能"吞云吐雾"?性能背后的秘密1.1 顺序写入与零拷贝:性能的双引擎1.2 分区并行:数据的"八车道高速公路"1.3 页缓存与批量处理…...
【若依】框架项目部署笔记
参考【SpringBoot】【Vue】项目部署_no main manifest attribute, in springboot-0.0.1-sn-CSDN博客 多一个redis安装 准备工作: 压缩包下载:http://download.redis.io/releases 1. 上传压缩包,并进入压缩包所在目录,解压到目标…...
DeepSeek越强,Kimi越慌?
被DeepSeek吊打的Kimi,还有多少人在用? 去年,月之暗面创始人杨植麟别提有多风光了。90后清华学霸,国产大模型六小虎之一,手握十几亿美金的融资。旗下的AI助手Kimi烧钱如流水,单月光是投流就花费2个亿。 疯…...
Canal环境搭建并实现和ES数据同步
作者:田超凡 日期:2025年6月7日 Canal安装,启动端口11111、8082: 安装canal-deployer服务端: https://github.com/alibaba/canal/releases/1.1.7/canal.deployer-1.1.7.tar.gz cd /opt/homebrew/etc mkdir canal…...
Yii2项目自动向GitLab上报Bug
Yii2 项目自动上报Bug 原理 yii2在程序报错时, 会执行指定action, 通过重写ErrorAction, 实现Bug自动提交至GitLab的issue 步骤 配置SiteController中的actions方法 public function actions(){return [error > [class > app\helpers\web\ErrorAction,],];}重写Error…...
[QMT量化交易小白入门]-六十二、ETF轮动中简单的评分算法如何获取历史年化收益32.7%
本专栏主要是介绍QMT的基础用法,常见函数,写策略的方法,也会分享一些量化交易的思路,大概会写100篇左右。 QMT的相关资料较少,在使用过程中不断的摸索,遇到了一些问题,记录下来和大家一起沟通,共同进步。 文章目录 相关阅读1. 策略概述2. 趋势评分模块3 代码解析4 木头…...
LeetCode 0386.字典序排数:细心总结条件
【LetMeFly】386.字典序排数:细心总结条件 力扣题目链接:https://leetcode.cn/problems/lexicographical-numbers/ 给你一个整数 n ,按字典序返回范围 [1, n] 内所有整数。 你必须设计一个时间复杂度为 O(n) 且使用 O(1) 额外空间的算法。…...
Qt 按钮类控件(Push Button 与 Radio Button)(1)
文章目录 Push Button前提概要API接口给按钮添加图标给按钮添加快捷键 Radio ButtonAPI接口性别选择 Push Button(鼠标点击不放连续移动快捷键) Radio Button Push Button 前提概要 1. 之前文章中所提到的各种跟QWidget有关的各种属性/函数/方法&#…...
