目录
3、mysql_real_connect()——数据库引擎建立连接
6、mysql_store_result()——向客户端检索完整的结果集
7、mysql_num_fields()——获取字段数量(列数)
8、mysql_free_result()——释放结果集使用的内存
9、mysql_fetch_row()——从结果集中获取下一行
前言
本博文是学习基于Linux+STM32+esp8266的超级智能无人超市项目里面所需要的一小些数据库使用,本博文便于学习这个项目的数据库部分,可以根据后面的最后一个使用实例来练习数据库的连接,表的删除和更正、查询!
一、安装软件
在电脑不同系统上安装使用MYSQL可以看这个视频:一小时MYSQL
二、普通指令使用
1、终端进入MYSQL:
mysql -u root -p
然后输入密码即可进入
2、创建数据库
我们可以先查询一下已经有的数据库:
show databases;
创建数据库:
CREATE DATABASE test;
test:数据库名字
指定使用哪个数据库:
use test;
创建表:
CREATE TABLE users(id VARCHAR(20) unique key,name VARCHAR(50),phone VARCHAR(15) unique key,balance VARCHAR(25),text VARCHAR(1000));
users:表名
查询表:
desc users; users:表名
退出MySQL:
exit;
插入操作:
"INSERT INTO me(pid, pname,price,brand) VALUES('123','lll','100','ddd')";
me:表名
查询操作:
"SELECT * FROM me";
me:表名
删除操作:
DELETE FROM me where name=0;
me:表名
删除me表中name为0的成员
删除全部成员:TRUNCATE TABLE usr;
usr:表名
更改操作:
UPDATE me set name = 0 where price = 100;
me:表名
将price为100的成员的name更改为0
三、MySQL接口API相关函数
1、API函数使用步骤
1,首先需要 mysql的头文件,并链接MQSQL动态库。
#include
2、创建MYSQL变量
MYSQL mysql;
3、mysql_init初始化MYSQL变量
4、调用mysql_real_connect函数连接Mysql数据库
5、调用mysql_real_query函数进行数据库查询
6、通过调用mysql_store_result或mysql_use_result函数返回的MYSQL_RES变量获取查询结果数据。
7、调用mysql_fetch_row函数读取结果集数据。
8、结果集用完后,调用mysql_free_result函数释放结果集,以防内存泄露
9、不再查询Mysql数据库时,调用mysql_close函数关闭数据库连接
2、mysql_init-MYSQL对象初始化
- MYSQL *mysql_init(MYSQL *mysql)
返回值:
- 初始化的MYSQL*句柄。如果无足够内存以分配新的对象,返回NULL。 错误,在内存不足的情况下,返回NULL。
说明:
-
如果mysql是NULL指针,该函数将分配、初始化、并返回新对象。
-
否则,将初始化对象,并返回对象的地址。
-
如果mysql_init()分配了新的对象,应当在程序中调用mysql_close() 来关闭连接,以释放对象
3、mysql_real_connect()——数据库引擎建立连接
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*连接句柄。
- 如果连接失败,返回NULL。对于成功的连接,返回值与第1个参数的值相同。
参数说明:
- mysql:前面定义的MYSQL变量;
- host:MYSQL服务器的地址;
- 如果“host”是NULL或字符串"localhost",连接将被视为与本地主机的连接。
- 如果操作系统支持套接字(Unix)或命名管道(Windows),将使用它们而不是TCP/IP连接到服务器。
- user:登录用户名;
- 如果“user”是NULL或空字符串"",用户将被视为当前用户。在UNIX环境下,它是当前的登录名。
- passwd:登录密码;
- db:要连接的数据库,如果db为NULL,连接会将默认的数据库设为该值。
- port:MYSQL服务器的TCP服务端口;
- 如果“port”不是0,其值将用作TCP/IP连接的端口号。注意,“host”参数决定了连接的类型。
- unix_socket:unix连接方式。
- 如果unix_socket不是NULL,该字符串描述了应使用的套接字或命名管道。注意,“host”参数决定了连接的类型。
- clientflag:Mysql运行为ODBC数据库的标记,一般取0。
4、mysql_close()——关闭数据库连接
- void mysql_close(MYSQL *mysql)
5、mysql_query()——查询数据库某表内容
查询数据库中的某一个表内容,通过函数mysql_query()来实现
- int mysql_query(MYSQL *mysql, const char *query)
- //query为执行的SQL语句对应的字符长串
返回值
- 如果查询成功,返回0。如果出现错误,返回非0值。
使用说明:
- 执行由“Null终结的字符串”查询指向的SQL查询。
- 正常情况下,字符串必须包含1条SQL语句,而且不应为语句添加终结分号(‘;’)或“\g”。如果允许多语句执行,字符串可包含多条由分号隔开的语句。(“多查询执行的C API处理”)
mysql_query()
不能用于包含二进制数据
的查询,应使用mysql_real_query()
取而代之(二进制数据可能包含字符‘\0’
,mysql_query()
会将该字符解释为查询字符串结束)。- 如果希望了解查询是否应返回结果集,可使用
mysql_field_count()
进行检查。 - 查询成功则该函数返回0。
使用实例:
- // 执行操作 SQL 语句(INSERT/UPDATE/DELETE)
- bool SQLifconfig_Dml_sql(SQLifconfig *config, const char *sqlstr) {
- printf("sql: %s\n", sqlstr);
-
- // 开始事务
- if (mysql_query(config->mysql, "BEGIN")) {
- printf("query_error: %s\n", mysql_error(config->mysql));
- return false;
- }
-
- // 执行 SQL 语句
- if (mysql_query(config->mysql, sqlstr)) {
- printf("query_error: %s\n", mysql_error(config->mysql));
- return false;
- }
-
- // 提交事务
- if (mysql_query(config->mysql, "COMMIT")) {
- printf("query_error: %s\n", mysql_error(config->mysql));
- return false;
- }
-
- return true;
- }
6、mysql_store_result()——向客户端检索完整的结果集
显示查询数据库中数据表的内容,mysql_store_result()
将mysql_query()
查询的全部结果读取到客户端,分配1个MYSQL_RES结构
(上面有介绍),并将结果置于该结构中
- MYSQL_RES *mysql_store_result(MYSQL *mysql)
返回值
具有多个结果的MYSQL_RES
结果集合。如果出现错误,返回NULL。
使用说明:
- 对于成功检索了数据的每个查询(
SELECT、SHOW、DESCRIBE、EXPLAIN、CHECK TABLE
等),必须调用mysql_store_result()
或mysql_use_result()
。 - 如果希望了解查询是否应返回结果集,可使用
mysql_field_count()
进行检查。 - 如果查询未返回结果集,
mysql_store_result()
将返回Null指针(例如,如果查询是INSERT语句)。 - 如果读取结果集失败,
mysql_store_result()
还会返回Null指针。通过检查mysql_error()
是否返回非空字符串
,mysql_errno()
是否返回非0值
,或mysql_field_count()
是否返回0
,可以检查是否出现了错误。 - 如果未返回行,将返回空的结果集。(空结果集设置不同于作为返回值的空指针)。
- 一旦调用了
mysql_store_result()
并获得了不是Null指针的结果,可调用mysql_num_rows()
来找出结果集中的行数
。 - 可以调用
mysql_fetch_row()
来获取结果集中的行,或调用mysql_row_seek()
和mysql_row_tell()
来获取或设置结果集中的当前行位置
。 - 一旦完成了对结果集的操作,必须调用mysql_free_result()。
7、mysql_num_fields()——获取字段数量(列数)
- int mysql_num_fields(MYSQL_RES *result)
8、mysql_free_result()——释放结果集使用的内存
释放由mysql_store_result()
、mysql_use_result()
、mysql_list_dbs()
等为结果集分配的内存。完成对结果集的操作后,必须调用mysql_free_result()
释放结果集使用的内存。
- void mysql_free_result(MYSQL_RES *result)
9、mysql_fetch_row()——从结果集中获取下一行
- MYSQL_ROW mysql_fetch_row(MYSQL_RES* result)
- //MYSQL_ROW开篇已经说明,char ** 类型
返回值
- 下一行的
MYSQL_ROW
结构。如果没有
更多要检索的行或出现了错误,返回NULL。
使用说明:
- 在
mysql_store_result()
之后使用时,如果没有要检索的行,mysql_fetch_row()
返回NULL。 - 在
mysql_use_result()
之后使用时,如果没有要检索的行或出现了错误,mysql_fetch_row()
返回NULL。 - 行内值的数目由
mysql_num_fields(result)
给出。如果行中保存了调用mysql_fetch_row()
返回的值,将按照row[0]
到row[mysql_num_fields(result)-1]
,访问这些值的指针。 - 可以通过调用
mysql_fetch_lengths()
来获得行中字段值的长度。对于空字段以及包含NULL的字段,长度为0。通过检查字段值的指针,能够区分它们。如果指针为NULL,字段为NULL,否则字段为空。
四、使用C语言连接MySQL
下面我们使用C语言来写函数来连接和使用MySQL
sql_connect.c:
- #include "sql_connect.h"
- #include
- #include
- #include
-
- // 初始化数据库连接对象
- SQLifconfig* SQLifconfig_init() {
- SQLifconfig *config = (SQLifconfig*)malloc(sizeof(SQLifconfig));
- if (!config) return NULL;
-
- // 初始化成员变量
- config->mysql = NULL;
- config->row = NULL;
- config->result = NULL;
- config->field = NULL;
-
- // 初始化 MySQL 连接
- config->mysql = mysql_init(NULL);//参数为NULL,函数将分配初始化,并初始化、返回新对象
- if (!config->mysql) {
- printf("Init Error: %s\n", mysql_error(config->mysql));
- free(config);
- return NULL;
- }
-
- // 强制设置字符集
- if (mysql_options(config->mysql, MYSQL_SET_CHARSET_NAME, "utf8mb4")) {
- printf("Set UTF-8 Error: %s\n", mysql_error(config->mysql));
- mysql_close(config->mysql);
- free(config);
- return NULL;
- }
-
- return config;
- }
-
- // 释放数据库连接对象
- void SQLifconfig_destroy(SQLifconfig *config) {
- if (config) {
- if (config->mysql) {
- mysql_close(config->mysql);//关闭数据库连接
- }
- free(config);//释放空间
- }
- }
-
- // 初始化数据库连接
- bool SQLifconfig_SQL_init(SQLifconfig *config, const char *host, const char *user, const char *pwd, const char *dbname) {
- if (!mysql_real_connect(config->mysql, host, user, pwd, dbname, 3306, NULL, 0)) {
- printf("connect error: %s\n", mysql_error(config->mysql));
- return false;
- }
- return true;
- }
-
- // 执行操作 SQL 语句(INSERT/UPDATE/DELETE)
- bool SQLifconfig_Dml_sql(SQLifconfig *config, const char *sqlstr) {
- printf("sql: %s\n", sqlstr);
-
- // 开始事务
- if (mysql_query(config->mysql, "BEGIN")) {
- printf("query_error: %s\n", mysql_error(config->mysql));
- return false;
- }
-
- // 执行 SQL 语句
- if (mysql_query(config->mysql, sqlstr)) {
- printf("query_error: %s\n", mysql_error(config->mysql));
- return false;
- }
-
- // 提交事务
- if (mysql_query(config->mysql, "COMMIT")) {
- printf("query_error: %s\n", mysql_error(config->mysql));
- return false;
- }
-
- return true;
- }
-
- // 执行查询 SQL 语句(SELECT)
- char* SQLifconfig_Dql_sql(SQLifconfig *config, const char *sqlstr) {
- // 执行 SQL 查询
- if (mysql_query(config->mysql, sqlstr)) {
- printf("query_error: %s\n", mysql_error(config->mysql));
- return NULL;
- }
-
- // 获取查询结果集
- config->result = mysql_store_result(config->mysql);
- if (!config->result) {
- return NULL; // 无结果或错误
- }
-
- // 获取字段数量(列数)
- int fieldnum = mysql_num_fields(config->result);
-
- // 初始化动态缓冲区
- size_t total_len = 1024; // 初始缓冲区大小
- char *buffer = (char*)malloc(total_len);
- if (!buffer) {
- mysql_free_result(config->result);
- return NULL; // 内存分配失败
- }
- buffer[0] = '\0'; // 初始化空字符串
-
- // 遍历结果集的每一行
- while ((config->row = mysql_fetch_row(config->result))) {
- // 计算当前行所需的总长度
- size_t row_len = 0;
- for (int j = 0; j < fieldnum; j++) {
- row_len += strlen(config->row[j] ? config->row[j] : "NULL") + 1; // 字段值 + 分隔符
- }
-
- // 动态扩展缓冲区(如果当前缓冲区不足以容纳新行)
- size_t current_len = strlen(buffer);
- if (current_len + row_len + 2 > total_len) {
- total_len += row_len + 2; // 扩展缓冲区大小
- char *new_buf = realloc(buffer, total_len);
- if (!new_buf) {
- free(buffer);
- mysql_free_result(config->result);
- return NULL; // 内存分配失败
- }
- buffer = new_buf;
- }
-
- // 拼接当前行的字段值
- for (int j = 0; j < fieldnum; j++) {
- const char *val = config->row[j] ? config->row[j] : "NULL"; // 处理 NULL 值
- strcat(buffer, val); // 追加字段值
- strcat(buffer, "#"); // 追加分隔符
- }
- buffer[strlen(buffer)-1] = '\n'; // 将最后一个#替换为换行符
- }
-
- // 释放结果集内存
- mysql_free_result(config->result);
-
- // 检查是否有有效数据
- if (strlen(buffer) == 0) {
- free(buffer);
- return NULL; // 无数据
- }
-
- // 返回格式化后的字符串
- return buffer;
- }
-
sql_connect.h:
- #ifndef __SQL_CONNECT_H
- #define __SQL_CONNECT_H
-
- #include
- #include
-
- // 数据库连接结构体
- typedef struct {
- MYSQL *mysql; // MySQL 连接对象
- MYSQL_ROW row; // 当前行数据
- MYSQL_RES *result; // 查询结果集
- MYSQL_FIELD *field; // 字段信息
- } SQLifconfig;
-
- // 初始化数据库连接
- SQLifconfig* SQLifconfig_init();
-
- // 释放数据库连接
- void SQLifconfig_destroy(SQLifconfig *config);
-
- // 初始化数据库连接
- bool SQLifconfig_SQL_init(SQLifconfig *config, const char *host, const char *user, const char *pwd, const char *dbname);
-
- // 执行查询 SQL 语句(SELECT)
- char* SQLifconfig_Dql_sql(SQLifconfig *config, const char *sqlstr);
-
- // 执行操作 SQL 语句(INSERT/UPDATE/DELETE)
- bool SQLifconfig_Dml_sql(SQLifconfig *config, const char *sqlstr);
-
- #endif
-
五、使用示例
5.1、连接初始化
建立两个表,并且数据库名为shopping,后面的实验都会围绕这两个表进行实验:
- CREATE DATABASE shopping;
-
- CREATE TABLE users(
- id VARCHAR(20) unique key,
- name VARCHAR(50),
- phone VARCHAR(15) unique key,
- balance VARCHAR(25),
- text VARCHAR(1000)
- )
-
- CREATE TABLE me(
- pid VARCHAR(20) unique key,
- pname VARCHAR(50),
- price VARCHAR(15),
- brand VARCHAR(25)
- )
- SQLifconfig *MySQL_Handler;
-
-
- int main()
- {
-
- // 初始化数据库连接对象
- MySQL_Handler = SQLifconfig_init();
- if (!MySQL_Handler) {
- printf("初始化数据库失败\n");
- return -1;
- }
- // 连接数据库 //数据库名字
- if (!SQLifconfig_SQL_init(MySQL_Handler, "127.0.0.1", "root", "123456", "shopping")) {
- printf("连接数据库失败\n");
- SQLifconfig_destroy(MySQL_Handler);
- return -1;
- }
-
- }
5.2、构造指令
下面就是一些项目中所使用到的指令,可能有一些没有写,不过应该是都写了,类似相同的就不写了!
- /* 删除me表中的pid为str的成员 */
- // 构造 SQL 删除语句
- sprintf(buf, "DELETE FROM me WHERE pid='%s'", str);
- // 执行 SQL 删除操作
- int result = SQLifconfig_Dml_sql(MySQL_Handler, buf);
-
- /* 查询users表中phone为str的成员的id, name, phone, balance */
- sprintf(buf, "SELECT id, name, phone, balance FROM users WHERE phone='%s'", str);
- // 执行查询
- char* ret = SQLifconfig_Dql_sql(MySQL_Handler, buf);
-
- /* 更新users表中的ide为pid的成员的balance ,修改为balance+num */
- sprintf(buf, "UPDATE users SET balance = balance + %d WHERE id='%s'", num, pid);
- if (SQLifconfig_Dml_sql(MySQL_Handler, buf))
-
- /* 删除users表中的所有成员 */
- SQLifconfig_Dml_sql(MySQL_Handler, "TRUNCATE TABLE users"))
-
-
-
-
-
-
-
-
-
-
- /* 可以用来练习 */
-
- //执行插入操作 //表名
- const char *insert_sql = "INSERT INTO users(id, name,phone,balance) VALUES('888','hxy','666',100)";
- if (SQLifconfig_Dml_sql(MySQL_Handler, insert_sql)) {// 执行操作 SQL 语句(INSERT/UPDATE/DELETE)
- printf("插入成功\n");
- } else {
- printf("插入失败\n");
- }
-
- insert_sql = "INSERT INTO me(pid, pname,price,brand) VALUES('888','hxy','666',100)";
- if (SQLifconfig_Dml_sql(MySQL_Handler, insert_sql)) {// 执行操作 SQL 语句(INSERT/UPDATE/DELETE)
- printf("插入成功\n");
- } else {
- printf("插入失败\n");
- }
-
-
- // 执行查询操作 //表名
- const char *select_sql = "SELECT * FROM users";
- char *result = SQLifconfig_Dql_sql(MySQL_Handler, select_sql);// 执行查询 SQL 语句(SELECT)
- if (result) {
- printf("查询结果:\n%s", result);
- free(result); // 必须手动释放内存
- } else {
- printf("查询失败或无结果\n");
- }
-
- select_sql = "SELECT * FROM me";
- result = SQLifconfig_Dql_sql(MySQL_Handler, select_sql);// 执行查询 SQL 语句(SELECT)
- if (result) {
- printf("查询结果:\n%s", result);
- free(result); // 必须手动释放内存
- } else {
- printf("查询失败或无结果\n");
- }
评论记录:
回复评论: