MySQL数据库访问

前提准备

要访问MySQL需要下载MySQL,下载时会一起下载MySQL客服端和服务端以及依赖。以C++/C访问MySQL需要用到MySQL提供的API接口,这些API可以在MySQL官网上找到。

yum install myaql-community-server

MySQL句柄

MYSQL* mysql=mysql_init(nullptr);

连接函数

MYSQL *mysql_real_connect(

MYSQL *mysql, // MySQL 连接句柄

const char *host, // 主机名或IP地址

const char *user, // MySQL用户名

const char *passwd, // 密码

const char *db, // 默认数据库

unsigned int port, // 端口号

const char *unix_socket,// Unix域套接字路径

unsigned long client_flag // 客户端标志

);

cpp 复制代码
#include <iostream>
#include <mysql/mysql.h>
#define HOST "localhost"  //或#define HOST "120.0.0.1"
#define USER "root"
#define PASSWORD "123456"
#define DB "conn"
#define PORT 3306
main()
{
    //......
    mysql = mysql_real_connect(mysql,HOST,USER,PASSWORD,DB,PORT,nullptr,0);
    if(mysql==nullptr)
    {
        std::cout<<"mysql_real_connect fail"<<std::endl;
        return 1;
    }
    //......
    return 0;
}

参数解释

mysql:mysql句柄,由mysql_init()初始化的连接句柄指针

host:主机名(如'localhost'或'127.0.0.1')

user:用户名如果为null,表示当前系统登录用户名

passwd:用户密码,如果为null,表示不使用密码

db:要使用的数据库名称,可以为null

port:mysql服务的端口号,为0就是默认端口3306

unix_socker:套接字路径,设置为null,表示默认套接字

client_flag:标志位,很少用到,设置为0

user为null解释

假设你住在一个小区(​​MySQL服务器​ ​),单元楼有门禁(​​MySQL的权限系统​​)。

方式1:用专属门禁卡(显式指定用户名)​

  • 你从钱包里掏出写有 ​​"业主A"​ ​ 的门禁卡(user="业主A"),刷卡进门。

  • ​结果​​:

    • 如果卡有效(用户存在且密码正确)→ 门开。

    • 如果卡无效(用户不存在)→ 被保安拦下。

方式2:刷脸(user=NULL,用系统用户名)​

  • 你没带门禁卡,直接走到摄像头前刷脸。

  • 系统自动识别你的脸,查出你是 ​​"住户B"​​(当前系统登录用户名),然后尝试用这个身份开门。

  • ​结果​​:

    • 如果小区登记过你的脸(MySQL有用户住户B)且无需密码 → 门开。

    • 如果没登记或需要密码但你没输入 → 保安拒绝进入。

所以user=null就像刷脸一样,方便但是不安全。

句柄的意义

句柄可以避免直接操作底层,借书的人不会去图书馆仓库找书,句柄隐藏了MySQL内部的复杂实现,如果借书不换,图书馆的书就会越来越少,所以申请的句柄,用完后就需要释放句柄。

  1. 办借书证 → mysql_init()mysql_real_connect()​​
  • 你需要先到前台 ​​办一张借书证​ ​(类似创建句柄 MYSQL* conn)。

  • 图书管理员(​​MySQL服务器​ ​)会登记你的信息(用户名、密码),然后给你一个 ​​借书证编号​​(句柄的值)。

    → 这个编号​​不是书本身​ ​,而是你借书的​​权限凭证​​。

  1. 查目录 → mysql_query()​​
  • 你用借书证去查图书目录(​​SQL查询​ ​),比如找"所有编程书"(SELECT * FROM books)。

  • 管理员给你一份​​临时书单​ ​(结果集句柄 MYSQL_RES* res),上面列出了书的位置和名字。

  1. 取书 → mysql_fetch_row()​​
  • 你根据书单去书架拿书(​​获取数据行​ ​)。每本书的​​内容​ ​(数据)是具体的,但书单(结果集)只是一个​​指向书的指针​​。

  • 每次拿一本(mysql_fetch_row),直到书架空了(返回NULL)。

  1. 还书 → mysql_free_result()mysql_close()​​
  • 读完书后,你要把​​书单归还​​(释放结果集),否则管理员会以为你还在用。

  • 最后​​退还借书证​​(关闭连接),否则图书馆会一直保留你的借阅名额(资源泄漏)。

设置客服端字符集

用vscode连接MySQL,这两者的编码方式可能不同,就需要以MySQL的编码方式为准,把vscode的编码同步。

mysql_set_character_set(mysql,"utf8");

选择数据库

刚开始的连接就包含了库的设置,后面出现选择数据库就可以调用这个函数。

mysql_select_db(mysql,"conn");

执行sql语句

mysql是申请的句柄,char的内容会变为字符串输入到mysql中,成功放回0,否则放回非零。

int mysql_query(MYSQL*, const char*)

示例

cpp 复制代码
std::string insert1 = "insert into stu values(null,'张三',18,187562354)";
n = mysql_query(mysql, insert1.c_str());
if (n != 0)
{
    std::cout << "mysql_query fail" << std::endl;
    return 1;
}

获取查询结构

在上面的代码中,char内容是select的话,是不会显示表的信息,select不像其它语句增删改,查的信息会保存在一个地方,需要使用API去获取信息。

MYSQL_RES* mysql_store_result(MYSQL*)

函数的返回值为MYSQL_RES* 类型,是一个结构体指针类型,保存了查询结构和相关属性,如下图,每一个char* 都指向表的一个内容,所以要查看表的内容,就需要遍历所有元素,打印出内容。

示例

MYSQL_RES *res = mysql_store_result(mysql);

if (res == nullptr)

{

std::cout << "mysql_store_result fail" << std::endl;

return 1;

}

获取行的个数

int row = mysql_num_rows(res);

获取列的个数

int col = mysql_num_fields(res);

遍历打印

MYSQL_ROW mysql_fetch_row(MYSQL_RES*)

这个函数没调用一次会自动+1,遍历第一行再次调用就到下一行了。

for (int i = 0; i < row; i++)

{

MYSQL_ROW r = mysql_fetch_row(res);

for (int j = 0; j < col; j++)

{

std::cout << r[j] << '/t';

}

std::cout << std::endl;

}

释放申请的资源

void mysql_free_result(MYSQL_RES*)

释放结果集

void mysql_close(MYSQL*);

释放句柄

总代码

cpp 复制代码
#include <iostream>
#include <mysql/mysql.h>
#define HOST "localhost" // 或#define HOST "120.0.0.1"
#define USER "root"
#define PASSWORD "XyK@71986582"
#define DB "conn"
#define PORT 3306
int main()
{
    // 创建MySQL句柄
    MYSQL *mysql = mysql_init(nullptr);
    // 连接数据库
    mysql = mysql_real_connect(mysql, HOST, USER, PASSWORD, DB, PORT, nullptr, 0);
    if (mysql == nullptr)
    {
        std::cout << "mysql_real_connect fail" << std::endl;
        return 1;
    }
    // 设置客户端字符集,与mysqld保持一致。
    int n = mysql_set_character_set(mysql, "utf8");
    if (n != 0)
    {
        std::cout << "mysql_setcharacter_set fail" << std::endl;
        return 1;
    }
    // 选择要操作的数据库
    // 在做连接时已经选好了现在就不用选,只是考虑到中途需要换其他库的情况。
    // n = mysql_select_db(mysql,"conn");
 
    // 准备工作做好了,接下来操作库:
    // 执行SQL语句
    std::string insert1 = "insert into stu values(null,'张三',18,187562354)";
    std::string insert2 = "insert into stu values(null,'李四',18,187562154)";
    std::string delete1 = "delete from stu where id=1";
    std::string update = "update stu set name='王五' where name = '李四'";
 
    std::string sel = "select * from stu";
    n = mysql_query(mysql, sel.c_str());
    if (n != 0)
    {
        std::cout << "mysql_query fail" << std::endl;
        return 1;
    }
    MYSQL_RES *res = mysql_store_result(mysql);
    if (res == nullptr)
    {
        std::cout << "mysql_store_result fail" << std::endl;
        return 1;
    }
    int row = mysql_num_rows(res);
    int col = mysql_num_fields(res);
    for (int i = 0; i < row; i++)
    {
        MYSQL_ROW r = mysql_fetch_row(res);
        for (int j = 0; j < col; j++)
        {
            std::cout << r[j] << '\t';
        }
        std::cout << std::endl;
    }
    mysql_free_result(res);
    mysql_close(mysql);
    return 0;
}
相关推荐
CS Beginner3 小时前
【Linux】安装配置mysql中出现的问题1
linux·mysql·adb
飘飞雪3 小时前
深入浅出kafka:kafka演进以及核心功能介绍
数据库·分布式·kafka
一个天蝎座 白勺 程序猿4 小时前
Python驱动Ksycopg2连接和使用Kingbase:国产数据库实战指南
数据库·python·kingbase·金仓数据库
高铭杰5 小时前
Postgresql源码(149)SIMD应用与性能测试
数据库·postgresql·sse·simd
来碗原味的小米粥吧6 小时前
sql题目基础50题
linux·数据库·sql
安当加密6 小时前
PostgreSQL透明加密(TDE)技术深度解析:从实现原理到国密合规实践
数据库·postgresql·区块链
云和数据.ChenGuang6 小时前
MongoDB 认证失败(错误码 18)
数据库·mongodb
程序新视界6 小时前
一篇文章详解你不知道的MySQL JSON数据类型
数据库·mysql·json
卷Java7 小时前
用户权限控制功能实现说明
java·服务器·开发语言·数据库·servlet·微信小程序·uni-app