MySQL在C/C++中的使用

1.初始化与连接函数

(1)mysql_init()

MYSQL *mysql_init(MYSQL *mysql);

功能:初始化 MySQL 连接句柄(结构体)

说明:若参数为 NULL,会自动分配新的句柄,需在最后用 mysql_close() 释放。

需要结合 mysql_close() 使用

功能:关闭 MySQL 连接并释放句柄

void mysql_close(MYSQL *mysql);

(2)mysql_real_connect()

功能:建立与 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 client_flag); MYSQL *mysql, 已初始化的句柄 const char *host, 服务器地址("localhost" 或 IP) const char *user, 用户名 const char *passwd, 密码 const char *db, 数据库名(可为 NULL,后续再选择) unsigned int port, 端口(通常为 3306,0 表示默认) const char *unix_socket,Unix 套接字(NULL 表示不使用) unsigned long client_flag 客户端标志(通常为 0)

说明:成功返回连接句柄,失败返回 NULL,可通过 mysql_error() 获取错误信息。

2. 执行 SQL 语句函数

(1)mysql_query()

功能:执行 SQL 语句(字符串形式,不含二进制数据) 

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

说明:成功返回 0,失败返回非 0。适合执行 SELECT、INSERT、UPDATE 等常规语句。

(2)mysql_real_query()

功能:执行 SQL 语句(支持包含二进制数据的语句)

int mysql_real_query( MYSQL *mysql, const char *stmt_str, unsigned long length // 语句长度(字节数) );

说明:与 mysql_query() 类似,但需显式指定语句长度,适合处理含特殊字符的 SQL。

3. 处理查询结果函数

(1)mysql_store_result()

功能:获取 SELECT 等查询的全部结果集(一次性加载到内存)

MYSQL_RES *mysql_store_result(MYSQL *mysql); 说明:成功返回结果集句柄,失败返回 NULL,需用 mysql_free_result() 释放。

(2)mysql_use_result()

功能:获取查询结果集(逐行读取,内存占用低)

MYSQL_RES *mysql_use_result(MYSQL mysql); 说明:适合处理大量数据,但需在读取完所有行后才能执行其他语句。 

4. 错误处理函数

(1)mysql_error()

功能:返回最近一次操作的错误信息

const char *mysql_error(MYSQL *mysql);

(2)mysql_errno()

功能:返回最近一次操作的错误代码

unsigned int mysql_errno(MYSQL *mysql);

5. 行数据处理函数

功能:获取结果集的字段数(列数)/ 行数 unsigned int mysql_num_fields(MYSQL_RES *result); // 列数 my_ulonglong mysql_num_rows(MYSQL_RES *result); // 行数

(1)mysql_fetch_row

功能:从结果集(MYSQL_RES*)中获取一行数据

MYSQL_ROW mysql_fetch_row(MYSQL_RES *result);

说明:
 - 返回值是 MYSQL_ROW 类型(本质是 char**,字符串数组),每个元素对应一列数据
 - 当无更多行或出错时返回 NULL
 - 数据以字符串形式存储(即使是数字类型,也需手动转换)

MYSQL_RES *res = mysql_store_result(my); if(res == nullptr) { std::cerr << "mysql_store_result error" << std::endl; return 4; } int rows = mysql_num_rows(res); int fields = mysql_num_fields(res); std::cout << "行:" << rows << std::endl; std::cout << "列:" << fields << std::endl; MYSQL_FIELD *fields_array = mysql_fetch_fields(res); for(int i = 0; i < rows; i++) { MYSQL_ROW row = mysql_fetch_row(res); for(int j = 0; j < fields; j++) { std::cout << row[j] << "\t"; } std::cout << "\n"; } 

虽然外层循环的变量 i 没有直接参与 mysql_fetch_row(res) 的调用,但循环本身起到了控制读取次数的作用,而 mysql_fetch_row 函数内部会维护一个 “当前行指针”,每次调用都会自动移动到下一行,这就是为什么能按行读取结果的核心原因。

(2)mysql_fetch_lengths()

功能:获取当前行中各字段的实际长度(字节数)

unsigned long *mysql_fetch_lengths(MYSQL_RES *result);

说明:
需在 mysql_fetch_row() 之后调用,获取当前行的字段长度数组
用于处理二进制数据或包含 \0 的字符串(避免被截断)
示例:

MYSQL_ROW row = mysql_fetch_row(result); unsigned long *lengths = mysql_fetch_lengths(result); for (int i = 0; i < cols; i++) {     // 安全处理字段数据(按实际长度读取)     printf("字段 %d: %.*s\n", i, lengths[i], row[i]); }

6. 字段(列)信息处理函数

(1)mysql_fetch_field()
功能:逐个获取结果集中的字段(列)元信息

MYSQL_FIELD *mysql_fetch_field(MYSQL_RES *result);

说明:
返回 MYSQL_FIELD 结构体指针,包含字段名、类型、长度等信息
多次调用可遍历所有字段,结束时返回 NULL
示例:

MYSQL_FIELD *field; while ((field = mysql_fetch_field(result))) {     printf("字段名: %s, 类型: %d, 长度: %lu\n",             field->name, field->type, field->length); }

(2)mysql_fetch_fields()
功能:一次性获取所有字段的元信息数组

MYSQL_FIELD *mysql_fetch_fields(MYSQL_RES *result);

说明:
返回字段信息数组的首地址,数组长度为 mysql_num_fields(result)
适合批量获取字段信息,无需循环调用 mysql_fetch_field()

typedef struct st_mysql_field { char *name; // 字段名称(列名) char *org_name; // 原始字段名(未被别名替换的名称) char *table; // 字段所属的表名 char *org_table; // 原始表名(未被别名替换的表名) char *db; // 字段所属的数据库名 char *catalog; // 目录名(通常为 "def") char *def; // 字段的默认值(字符串形式) unsigned long length; // 字段的显示长度(字节数) unsigned long max_length; // 结果集中该字段的最大实际长度(由 mysql_store_result 计算) 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; // 字段的标志(如是否为 NULL、主键等,见下文详解) unsigned int decimals; // 小数位数(用于数值类型,如 DECIMAL) unsigned int charsetnr; // 字符集编号(对应 MySQL 的字符集编码) enum enum_field_types type; // 字段的数据类型(见下文详解) void *extension; // 扩展信息(预留字段,通常不用) } MYSQL_FIELD;

示例:

int cols = mysql_num_fields(result); MYSQL_FIELD *fields = mysql_fetch_fields(result); for (int i = 0; i < cols; i++) {     printf("字段 %d: %s\n", i, fields[i].name); }

7. 结果集定位与遍历函数

(1)mysql_data_seek()
功能:在结果集中定位到指定行(随机访问)

void mysql_data_seek(MYSQL_RES *result, my_ulonglong offset);

说明:
仅对 mysql_store_result() 获取的结果集有效(全量加载到内存)
offset 为行索引(从 0 开始),需小于 mysql_num_rows(result)
示例:定位到第 5 行(索引 4)

mysql_data_seek(result, 4); MYSQL_ROW row = mysql_fetch_row(result); // 获取第5行数据

(2)mysql_row_seek()

功能:通过行偏移量(MYSQL_ROW_OFFSET)定位行

MYSQL_ROW_OFFSET mysql_row_seek(MYSQL_RES *result, MYSQL_ROW_OFFSET offset);

说明:
比 mysql_data_seek() 更底层,偏移量通过 mysql_row_tell() 获取
适用于需要保存 / 恢复行位置的场景

(3)mysql_row_tell()

功能:获取当前行在结果集中的偏移量

MYSQL_ROW_OFFSET mysql_row_tell(MYSQL_RES *result);

说明:
返回当前行的 MYSQL_ROW_OFFSET 类型偏移量,可用于 mysql_row_seek()

8. 其他实用函数

(1)mysql_affected_rows()

功能:获取上一条 INSERT/UPDATE/DELETE 语句影响的行数

my_ulonglong mysql_affected_rows(MYSQL *mysql);

说明:
对于 INSERT,返回插入的行数;对于 UPDATE/DELETE,返回受影响的行数
失败时返回 (my_ulonglong)-1

(2)mysql_insert_id()

功能:获取上一条 INSERT 语句生成的自增 ID(如主键 AUTO_INCREMENT)

my_ulonglong mysql_insert_id(MYSQL *mysql);

说明:
仅对包含自增字段的表有效,且需在 INSERT 执行后立即调用
这些函数主要用于精细化处理查询结果,包括行数据读取、字段元信息获取、结果集定位等,配合之前提到的核心函数可以完成复杂的数据库操作。

Read more

Flutter 三方库 at_server_status 的鸿蒙化适配指南 - 在鸿蒙系统上构建极致、透明、实时的 @protocol 去中心化身份服务器状态感知与鉴权监控引擎

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.ZEEKLOG.net Flutter 三方库 at_server_status 的鸿蒙化适配指南 - 在鸿蒙系统上构建极致、透明、实时的 @protocol 去中心化身份服务器状态感知与鉴权监控引擎 在鸿蒙(OpenHarmony)系统的隐私保护应用、去中心化身份管理工具(基于 @protocol 协议)或需要实时监控全球分布式节点健康状况的场景中,如何判定一个 @sign(电子签名标识)背后的 Root 服务器或 Secondary 服务器是否在线、配置是否由于由于由于由于已就绪?at_server_status 为开发者提供了一套工业级的、基于协议栈的状态审计与自检方案。本文将深入实战其在鸿蒙 Web3 身份安全底座中的应用。 前言 什么是 atServer Status?它是 @protocol(一种旨在让用户完全掌控数据的去中心化协议)官方生态的核心组件。

By Ne0inhk
鸿蒙金融理财全栈项目——生态合作、用户运营、数据变现

鸿蒙金融理财全栈项目——生态合作、用户运营、数据变现

《鸿蒙APP开发从入门到精通》第19篇:鸿蒙金融理财全栈项目——生态合作、用户运营、数据变现 📊🌍💰 内容承接与核心价值 这是《鸿蒙APP开发从入门到精通》的第19篇——生态合作、用户运营、数据变现篇,100%承接第18篇的风险控制、合规审计、产品创新架构,并基于金融场景的生态合作、用户运营、数据变现要求,设计并实现鸿蒙金融理财全栈项目的生态合作、用户运营、数据变现功能。 学习目标: * 掌握鸿蒙金融理财项目的生态合作设计与实现; * 实现金融机构合作、支付渠道合作、数据分析合作; * 理解用户运营在金融场景的核心设计与实现; * 实现用户增长、用户留存、用户转化; * 掌握数据变现在金融场景的设计与实现; * 实现数据服务、数据产品、数据变现; * 优化金融理财项目的用户体验(生态合作、用户运营、数据变现)。 学习重点: * 鸿蒙金融理财项目的生态合作设计原则; * 用户运营在金融场景的应用; * 数据变现在金融场景的设计要点。 一、 生态合作基础 🎯 1.1 生态合作定义 生态合作是指金融理财项目与其他金融机构、

By Ne0inhk

Flutter 三方库 encrypter_plus 的鸿蒙化适配指南 - 打造工业级多重加密隔离、安全存储实战、鸿蒙级数据隐私专家

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.ZEEKLOG.net Flutter 三方库 encrypter_plus 的鸿蒙化适配指南 - 打造工业级多重加密隔离、安全存储实战、鸿蒙级数据隐私专家 在鸿蒙跨平台应用处理用户核心资产、敏感通讯或离线隐私数据库时,单一的加密手段往往难以应对复杂的逆向工程攻击。我们需要一套功能全面、算法严谨且易于在鸿蒙端进行多层加固的方案。今天我们要深度解析的 encrypter_plus——一个集成了 AES、RSA、Salsa20 等多种主流算法的增强型加密工具集,正是帮你构建“数据保险柜”的核心组件。 前言 encrypter_plus 是对经典 encrypt 库的功能增强与性能优化版。它提供了更直观的操作符抽象和更健壮的填充(Padding)机制。在鸿蒙端项目中,利用它你可以轻松实现前端文件加密、服务端通讯非对称握手以及本地敏感配置的字段级混淆,确保即使用户设备的物理文件被导出,数据依然处于不可读的“致密状态”。 一、原理解析 / 概念介绍 1.1

By Ne0inhk
终于把LLaMA 2跑起来了,然后呢?本地大模型部署的残酷真相!

终于把LLaMA 2跑起来了,然后呢?本地大模型部署的残酷真相!

“终于把LLaMA 2跑起来了!” 深夜11点,程序员小林在朋友圈晒出电脑屏幕截图——黑色命令行窗口里,一行行代码滚动后,本地大模型吐出了第一句回答。他兴奋地刷新着评论区,看着“大佬”“技术牛”的赞美,感觉自己摸到了AI时代的“核心门槛”。 可这份热情没能撑过一个月。如今,那台专门升级了显卡的电脑,大模型程序静静躺在硬盘深处,偶尔开机,也只是为了清理缓存。“生成一句话要等10秒,写周报还能把部门名写错,不如直接用GPT-4 API,3秒出结果还靠谱。”小林的话,道出了无数本地部署玩家的心声。 2023年以来,“本地部署大模型”成了AI圈的热门话题。从技术博主的“手把手教程”,到论坛里的“配置交流帖”,仿佛人人都能拥有一台“私人AI服务器”。但热闹背后,是一场无声的“弃坑潮”:某技术社区调研显示,70%的个人用户在部署完成后3个月内停止使用,曾经的“技术勋章”,最终沦为“电子垃圾”。 这股热情的消退,绝非偶然。当“掌控AI”

By Ne0inhk