MySQL数据库入门
目录
前言
一、安装软件
二、普通指令使用
三、MySQL接口API相关函数
1、API函数使用步骤
2、mysql_init-MYSQL对象初始化
3、mysql_real_connect()——数据库引擎建立连接
4、mysql_close()——关闭数据库连接
5、mysql_query()——查询数据库某表内容
6、mysql_store_result()——向客户端检索完整的结果集
7、mysql_num_fields()——获取字段数量(列数)
8、mysql_free_result()——释放结果集使用的内存
9、mysql_fetch_row()——从结果集中获取下一行
四、使用C语言连接MySQL
五、使用示例
5.1、连接初始化
5.2、构造指令
前言
本博文是学习基于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 <mysql.h>
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 <stdio.h>
#include <stdlib.h>
#include <string.h>
// 初始化数据库连接对象
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 <mysql.h>
#include <stdbool.h>
// 数据库连接结构体
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");
}