MySQL访问个人学习笔记

一、MySQL访问的本质

在前面几篇博客中已完成了数据库的基本使用和原理相关学习和梳理,本篇介绍如何使用语言连接MySQL。

已知MySQL有客户端和服务端,程序员要做的就是编写业务逻辑,将需求发给客户端,客户端进而访问服务端,并将结果返回给主程序(所以一开始在shell中调用systemctl start mysql就是启动服务端进程,而mysql登录就是打开客户端并连接服务器)


二、访问相关方法介绍

为了操作数据库资源,一开始需创建对应的MYSQL结构体对象 并初始化。像这种用于在程序中唯一标识、引用和操作特定的对象或系统资的数据类型通常被称为句柄。

cpp 复制代码
MYSQL *my = mysql_init(NULL);

初始化完毕后,需连接到数据库(如果是远端登录,要求数据库提前创建好允许远端登录的用户)用户需要具备操作的权限。连接需要的参数大多和在shell上进行MySQL登录用到的差不多。

需注意的是,链接也有自己的字符集,可以理解成当前程序的字符集,比如你要插入数据的话是以当前程序的字符集为标准的。而已为了不和数据库字符集冲突,需要重新设置链接字符集。

cpp 复制代码
mysql_set_character_set(my, "utf8");

代码示例如下:

cpp 复制代码
//函数原型:
/*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 clientflag);*/
const std::string host = "127.0.0.1";//本地登录
const std::string user = "Cuser";
const std::string passward = "1234567";
const std::string db = "Ctest";//数据库名
const unsigned int port = 3306;//这里端口号和mysql配置文件中的端口号相同,可查询或修改
int main()
{
// printf("mysql client Version: %s\n", mysql_get_client_info());
MYSQL *my = mysql_init(NULL); // 初始化MYSQL类
if (my == nullptr)
{
std::cerr << "mysql init fail" << std::endl;
return 1;
}
// 连接数据库
if (mysql_real_connect(my, host.c_str(), user.c_str(), passward.c_str(), db.c_str(), port, nullptr, 0) == nullptr)
{
std::cerr << "mysql connect fail" << std::endl;
return 2;
}
// 无法连接
std::cout << "mysql connect success" << std::endl;
// 更改编码集
mysql_set_character_set(my, "utf8");
}

随后就可以调用接口操作数据库了:

cpp 复制代码
std::string insertsql="insert into user values('张三',555,'金榜花园')";
int flag = mysql_query(my, insertsql.c_str());
if (flag < 0)
{
    std::cerr << "do sql fail" << std::endl;
    return 3;
}

插入、删除和修改都是单向的,客户端只需要返回是否执行成功即可,比较复杂的是查询语句,即便客户端能把结果给到主程序,也需要配套的读取数据的机制。

当读取命令执行成功后,创建MYSQL_RES结构体指针并调用mysql_store_resul函数来接收指定MYSQL对象的结果。既然创建的是指针,说明函数自动为其申请了空间,使用完毕后需释放。

cpp 复制代码
MYSQL_RES *res = mysql_store_result(my);
/*后续操作...*/
mysql_free_result(res);//释放结果集

数据在MYSQL_RES结构体中的存放形式如图:

在一维数组中存放数据行数个char**,每个二级指针又指向一个char*数组,每个char*指向的就是某行某列的数据。随后可以调用mysql_num_rows()和mysql_num_fields()获取返回数据的行列数,再引入MYSQL_ROW(char**类型别名)并调用 mysql_fetch_row()来获取单行指针(该结构相当于指向结果某行的char**),根据行数决定要调用多少次mysql_fetch_row(),根据列数遍历具体全部数据。

注1:mysql_fetch_row()每次调用后会自动指向下一行,不需要主程序控制。

注2:如果想获取列名则调用mysql_fetch_fields(),一次返回所有字段定义的数组,配合mysql_num_fields()使用

代码如下:

cpp 复制代码
 MYSQL_RES *res = mysql_store_result(my);
    int row = mysql_num_rows(res);
    int fi = mysql_num_fields(res);
    MYSQL_FIELD *field = mysql_fetch_fields(res);
    int i = 0;
    for (; i < fi; i++)
    {
        std::cout << field[i].name << " ";
    }
    std::cout << std::endl;
    i = 0;
    MYSQL_ROW line;
    for (; i < row; i++)
    {
        line = mysql_fetch_row(res);
        int j = 0;
        for (; j < fi; j++)
        {
            std::cout << line[j] << " ";
        }
        std::cout << std::endl;
    }

三、浅谈从网页到数据库的流程

注册

  1. 在正式提供服务之前,需要提前为待存放的数据建立多个数据库。

  2. 用户打开浏览器网页,发起连接请求(即三次握手那一套流程),服务器随即应答并返回登录页面。

  3. 用户点击注册,跳转到注册页面后输入用户名和密码

  4. 服务器通过脚本语言(如 Java、Python 等)对请求进行解析,随后经由中间件和负载均衡机制,将数据分发到对应的数据库及数据表中。

  5. 各数据库之间会定期进行数据同步,以保证数据的一致性。
    登录

  6. 浏览器会先检查该账号是否存在 Cookie 缓存,若存在则可能直接完成登录(需要注意的是,Cookie 并非账号密码的副本,而是用于验证当前会话是否有效的标志)

  7. 若不存在,服务器会先调用 select 语句验证该账号在数据库中是否存在

  8. 若存在则正常登录,即校验密码哈希运算的结果是否与数据库中的记录相匹配。

相关推荐
Decay__3 小时前
05_MySQL 常用 SQL 大全 —— 诊断、管理、优化辅助 SQL 与三大系统库速查
运维·数据库·sql·mysql·架构
代码山河5 小时前
Python就业方向全解析:后端、爬虫、数据分析、AI你选哪个?
python·学习·架构·教程·面向对象·项目
sbjdhjd6 小时前
网工进阶笔记:H3CSE 园区网全栈技术与协议汇总
网络·笔记·云计算·ssh·网络工程·vlan·aaa
释厄6236 小时前
AI学习层更新与跨体转移律——人类社会同构·不缺理解缺 U
人工智能·学习
Decay__9 小时前
04_MySQL DBA 日常运维手册 —— 会话管理、锁与阻塞、事务监控、慢查询与日志巡检
运维·数据库·sql·mysql·架构
海绵宝宝的月光宝盒9 小时前
14-AutoCAD-阵列命令应用与案例实战(AR)
经验分享·笔记·自动化·课程设计·制造·学习方法·cad
小嘉丶学长10 小时前
Day14 · 字典与集合
java·开发语言·网络·python·学习·1024程序员节
白山编程大哥10 小时前
接口幂等性是什么?如何设计?
笔记
ACP广源盛1392462567310 小时前
6 盘位存储扩展方案选型笔记:YLB3116 @ACP评估记录
笔记·硬件架构·硬件工程·国产芯片
小李不想当小白10 小时前
SPI通信外设与W25Q64 (硬件SPI)(STM32标准库学习笔记)
笔记·stm32·单片机·嵌入式硬件·学习·嵌入式