MySQL·C/C++访问数据库

news2024/9/20 5:59:00

目录

准备工作

测试是否安装成功

C/C++语言访问

官方文档

接口介绍使用

mysql_init()

mysql_close() 

补充1:makefile编写

mysql_real_connect() 

测试1:编译链接

mysql_query()

测试2:SQL语句测试

改 

错误1:SQL语句错误

错误2:编码错误

mysql_set_character_set()

测试3:编码错误测试

查询的后序处理

mysql_store_result()

mysql_num_rows() 

mysql_num_fields()

测试4:行列获取测试

mysql_fetch_row()

测试5:读取数据测试

mysql_fetch_fields()

测试6:读取数据测试

mysql_free_result()

补充2:事务

全部的测试代码


准备工作

首先我们创建一个用户 参考上文MySQL·用户管理-CSDN博客

赋予权限

登入与权限测试

方法一:动静态链接 

C库下载

链接:MySQL :: MySQL Community Downloads

找到C版本支持的第三方库下载对应版本即可

方法二:yum源直接安装

参考下文: 

MySQL卸载、安装、登入与配置_yum 卸载mysql-CSDN博客

曾经安装过了,就不再演示了 

假如还是没有可以尝试直接安装

yum install mysql-devel

如果是一路看过来的话,可能你们的yum源需要更新了,我使用的源目前是有一些是无法访问的,但是到现在还没有什么影响,所以为了防止出现意外,就继续使用了。具体错误如下

测试是否安装成功

这是一个返回MySQL版本的一个函数,我们可以用它来做测试 

#include <iostream>
#include <mysql/mysql.h>

int main()
{
    std::cout << "mysql client version: " << mysql_get_client_info() << std::endl;
    return 0;
}

 直接编译是无法成功的,我们需要指定动态库

只指明库名也是无法成功的,我们还需要添加路径

g++ -o mytest test.cc -L/lib64/mysql/ -lmysqlclient

这样我们发现编译成功了,并且成功返回了MySQL的版本号

没有找到可以是因为这个的指明是无法找到,需要重新配置环境

你可能需要把环境添加到这里面来 

通常情况下,MySQL的安装程序会自动配置好所需的环境变量和库路径,你可能不需要手动进行这些操作。

解决方法可以参考下面这里的回答

如果在头文件中不指明文件夹的话,则需要在编译指令中添加文件夹

#include <iostream>
#include <mysql.h>

int main()
{
    std::cout << "mysql client version: " << mysql_get_client_info() << std::endl;
    return 0;
}

直接编译会报错 

添加大 -I 选项 

C/C++语言访问

官方文档

MySQL :: MySQL Documentation

找到C的,对应版本 

 

官方接口 :MySQL :: MySQL 5.7 C API Developer Guide :: 4 C API Function Reference

接口介绍使用

mysql_init()

MySQL :: MySQL 5.7 C API Developer Guide :: 5.4.37 mysql_init()

创建一个mysql类的结构体

MySQL类里面就是一些信息

mysql_close() 

MySQL :: MySQL 5.7 C API Developer Guide :: 5.4.5 mysql_close()

关闭释放这个句柄 

创建并且关闭 

#include <iostream>
#include <mysql/mysql.h>

int main()
{
    // std::cout << "mysql client version: " << mysql_get_client_info() << std::endl;

    // 创建一个mysql句柄
    MYSQL *my = mysql_init(nullptr);
    if(nullptr == my)
    {
        std::cerr << "init MySQL error" << std::endl;
        return 1;
    }

    // 关闭释放该句柄
    mysql_close(my);
    return 0;
}

 

编译测试 

补充1:makefile编写
mytest:test.cc
	g++ -o $@ $^ -std=c++11 -L/lib64/mysql -lmysqlclient
.PHONY:clean
clean:
	rm -f mytest
#上面的原式 g++ -o mytest test.cc -std=c++11 -L/lib64/mysql -lmysqlclient
#其中$@ $^表示自动变量,前者表示目标项,后者表示全部依赖项,$<表示第一个依赖项

mysql_real_connect() 

MySQL :: MySQL 5.7 C API Developer Guide :: 5.4.54 mysql_real_connect() 

链接数据库 

#include <iostream>
#include <string>
#include <mysql/mysql.h>

// const std::string host = "127.0.0.1";
const std::string host = "localhost";   // 使用本地回环也可以
const std::string user = "connector";
const std::string passwd = "123456";
const std::string db = "conn";
const unsigned int port = 8080;

int main()
{
    // std::cout << "mysql client version: " << mysql_get_client_info() << std::endl;

    // 创建一个mysql句柄
    MYSQL *my = mysql_init(nullptr);
    if(nullptr == my)
    {
        std::cerr << "init MySQL error" << std::endl;
        return 1;
    }
    if(mysql_real_connect(my, host.c_str(), user.c_str(), passwd.c_str(), db.c_str(), port, nullptr, 0) == nullptr)
    {
        std::cerr << "connect MySQL error" << std::endl;
        return 2;
    }
    std::cout << "connnect success" << std::endl;
    // 关闭释放该句柄
    mysql_close(my);
    return 0;
}

 

测试1:编译链接

  

为了方便演示,我们先创建一张表

create table user(
    id bigint primary key auto_increment,
    name varchar(32) not null,
    age int not null,
    telphone varchar(32) unique
    );

显然这里是没有什么问题的

我们可以通过下面这条SQL语句查看当前链接的用户信息 

show processlist;

 

我们对代码进行修改,让它不要这么快退出,让我们看到链接的信息

#include <iostream>
#include <unistd.h>
#include <string>
#include <mysql/mysql.h>

// const std::string host = "127.0.0.1";
const std::string host = "localhost";   // 使用本地回环也可以
const std::string user = "connector";
const std::string passwd = "123456";
const std::string db = "conn";
const unsigned int port = 8080;

int main()
{
    // std::cout << "mysql client version: " << mysql_get_client_info() << std::endl;

    // 创建一个mysql句柄
    MYSQL *my = mysql_init(nullptr);
    if(nullptr == my)
    {
        std::cerr << "init MySQL error" << std::endl;
        return 1;
    }
    if(mysql_real_connect(my, host.c_str(), user.c_str(), passwd.c_str(), db.c_str(), port, nullptr, 0) == nullptr)
    {
        std::cerr << "connect MySQL error" << std::endl;
        return 2;
    }
    sleep(10);
    std::cout << "connnect success" << std::endl;
    // 关闭释放该句柄
    mysql_close(my);
    return 0;
}

这一次我们看到了 

显然目前没有出现什么错误

mysql_query()

MySQL :: MySQL 5.7 C API Developer Guide :: 5.4.53 mysql_query()

下达指令 

#include <iostream>
#include <unistd.h>
#include <string>
#include <mysql/mysql.h>

// const std::string host = "127.0.0.1";
const std::string host = "localhost";   // 使用本地回环也可以
const std::string user = "connector";
const std::string passwd = "123456";
const std::string db = "conn";
const unsigned int port = 8080;

int main()
{
    // std::cout << "mysql client version: " << mysql_get_client_info() << std::endl;

    // 创建一个mysql句柄
    MYSQL *my = mysql_init(nullptr);
    if(nullptr == my)
    {
        std::cerr << "init MySQL error" << std::endl;
        return 1;
    }
    if(mysql_real_connect(my, host.c_str(), user.c_str(), passwd.c_str(), db.c_str(), port, nullptr, 0) == nullptr)
    {
        std::cerr << "connect MySQL error" << std::endl;
        return 2;
    }
    std::string sql;
    while(true)
    {
        std::cout << "MySQL>>> ";
        if(!std::getline(std::cin, sql) || sql == "quit")
        {
            std::cout << "bye bye" << std::endl;
            break;
        }
        int n = mysql_query(my, sql.c_str());
        if(n == 0)
        {
            std::cout << sql << " success: " << n << std::endl;
        }
        else
        {
            std::cerr << sql << " failed: " << n << std::endl;
        }
    }
    // sleep(10);
    // std::cout << "connnect success" << std::endl;
    // 关闭释放该句柄
    mysql_close(my);
    return 0;
}

 

测试2:SQL语句测试

改 

不过其实我们并不需要这么麻烦去写一个MySQL的客户端,我们只需要使用即可

#include <iostream>
#include <unistd.h>
#include <string>
#include <mysql/mysql.h>

// const std::string host = "127.0.0.1";
const std::string host = "localhost";   // 使用本地回环也可以
const std::string user = "connector";
const std::string passwd = "123456";
const std::string db = "conn";
const unsigned int port = 8080;

int main()
{
    // std::cout << "mysql client version: " << mysql_get_client_info() << std::endl;

    // 创建一个mysql句柄
    MYSQL *my = mysql_init(nullptr);
    if(nullptr == my)
    {
        std::cerr << "init MySQL error" << std::endl;
        return 1;
    }
    if(mysql_real_connect(my, host.c_str(), user.c_str(), passwd.c_str(), db.c_str(), port, nullptr, 0) == nullptr)
    {
        std::cerr << "connect MySQL error" << std::endl;
        return 2;
    }
    std::string sql = "update user set name='Jimmy' where id=2";
    int n = mysql_query(my, sql.c_str());
    if(n == 0) std::cout << sql << " success: " << n << std::endl;
    else std::cerr << sql << " failed: " << n << std::endl;
    /*
    // 其实我们并不需要这么麻烦去写一个MySQL的客户端,我们只需要使用即可
    std::string sql;
    while(true)
    {
        std::cout << "MySQL>>> ";
        if(!std::getline(std::cin, sql) || sql == "quit")
        {
            std::cout << "bye bye" << std::endl;
            break;
        }
        int n = mysql_query(my, sql.c_str());
        if(n == 0)
        {
            std::cout << sql << " success: " << n << std::endl;
        }
        else
        {
            std::cerr << sql << " failed: " << n << std::endl;
        }
    }
    */
    // sleep(10);
    // std::cout << "connnect success" << std::endl;
    // 关闭释放该句柄
    mysql_close(my);
    return 0;
}

显然这里是没有出现什么错误的,我们能够使用语言来实现对数据的控制

下面进行增删改查测试

#include <iostream>
#include <unistd.h>
#include <string>
#include <mysql/mysql.h>

// const std::string host = "127.0.0.1";
const std::string host = "localhost";   // 使用本地回环也可以
const std::string user = "connector";
const std::string passwd = "123456";
const std::string db = "conn";
const unsigned int port = 8080;

int main()
{
    // std::cout << "mysql client version: " << mysql_get_client_info() << std::endl;

    // 创建一个mysql句柄
    MYSQL *my = mysql_init(nullptr);
    if(nullptr == my)
    {
        std::cerr << "init MySQL error" << std::endl;
        return 1;
    }
    if(mysql_real_connect(my, host.c_str(), user.c_str(), passwd.c_str(), db.c_str(), port, nullptr, 0) == nullptr)
    {
        std::cerr << "connect MySQL error" << std::endl;
        return 2;
    }
    // std::string sql = "update user set name='Jimmy' where id=2"; // 改
    // std::string sql = "insert into user (name, age, telphone) values ('peter', 19, '987654321')";
    // std::string sql = "delete from user where id=1";
    std::string sql = "select * from user";

    int n = mysql_query(my, sql.c_str());
    if(n == 0) std::cout << sql << " success: " << n << std::endl;
    else std::cerr << sql << " failed: " << n << std::endl;
    /*
    // 其实我们并不需要这么麻烦去写一个MySQL的客户端,我们只需要使用即可
    std::string sql;
    while(true)
    {
        std::cout << "MySQL>>> ";
        if(!std::getline(std::cin, sql) || sql == "quit")
        {
            std::cout << "bye bye" << std::endl;
            break;
        }
        int n = mysql_query(my, sql.c_str());
        if(n == 0)
        {
            std::cout << sql << " success: " << n << std::endl;
        }
        else
        {
            std::cerr << sql << " failed: " << n << std::endl;
        }
    }
    */
    // sleep(10);
    // std::cout << "connnect success" << std::endl;
    // 关闭释放该句柄
    mysql_close(my);
    return 0;
}

我们会发现这个操作是无法进行的,因为查是这四种操作最不好处理的,因为这个消息并不是让服务端去显示,在使用的时候,我们肯定是要让用户去看到这个查的消息,这个我们在后面进行详细介绍

 

错误1:SQL语句错误

从这里看到,当用户传递的SQL语句不正确的时候,MySQL的服务端是不会进行处理的,当然这也是我们可以预料到的,因为MySQL保证对数据的操作,只要是成功的,就一定是正确的SQL语句,反之如果失败的,就一定是错误的语句

错误2:编码错误

我们可以看到,这里插入中文的话,是会出现乱码的,但是我们知道的,在一开始我们就已经配置好了MySQL的编码格式,那么为什么这里还是会出现呢?

如下我们配置里面是使用的utf8的

        这其实是因为编码的不一致导致的,建立好链接之后,获取英文没有问题,如果获取中文是乱码:设置链接的默认字符集是utf8,原始默认是latin1

mysql_set_character_set()

MySQL :: MySQL 5.7 C API Developer Guide :: 5.4.69 mysql_set_character_set()

设置编码格式

测试3:编码错误测试
#include <iostream>
#include <unistd.h>
#include <string>
#include <mysql/mysql.h>

// const std::string host = "127.0.0.1";
const std::string host = "localhost";   // 使用本地回环也可以
const std::string user = "connector";
const std::string passwd = "123456";
const std::string db = "conn";
const unsigned int port = 8080;

int main()
{
    // std::cout << "mysql client version: " << mysql_get_client_info() << std::endl;

    // 创建一个mysql句柄
    MYSQL *my = mysql_init(nullptr);
    if(nullptr == my)
    {
        std::cerr << "init MySQL error" << std::endl;
        return 1;
    }
    if(mysql_real_connect(my, host.c_str(), user.c_str(), passwd.c_str(), db.c_str(), port, nullptr, 0) == nullptr)
    {
        std::cerr << "connect MySQL error" << std::endl;
        return 2;
    }
    mysql_set_character_set(my, "utf8");

    // std::string sql = "update user set name='Jimmy' where id=2"; // 改
    // std::string sql = "insert into user (name, age, telphone) values ('peter', 19, '987654321')";
    // std::string sql = "delete from user where id=1";
    // std::string sql = "select * from user";
    std::string sql = "insert into user (name, age, telphone) values ('张三', 19, '666666666')";

    int n = mysql_query(my, sql.c_str());
    if(n == 0) std::cout << sql << " success: " << n << std::endl;
    else std::cerr << sql << " failed: " << n << std::endl;
    /*
    // 其实我们并不需要这么麻烦去写一个MySQL的客户端,我们只需要使用即可
    std::string sql;
    while(true)
    {
        std::cout << "MySQL>>> ";
        if(!std::getline(std::cin, sql) || sql == "quit")
        {
            std::cout << "bye bye" << std::endl;
            break;
        }
        int n = mysql_query(my, sql.c_str());
        if(n == 0)
        {
            std::cout << sql << " success: " << n << std::endl;
        }
        else
        {
            std::cerr << sql << " failed: " << n << std::endl;
        }
    }
    */
    // sleep(10);
    // std::cout << "connnect success" << std::endl;
    // 关闭释放该句柄
    mysql_close(my);
    return 0;
}

这下插入就没有编码不一致带来的乱码了

查询的后序处理

mysql_store_result()

MySQL :: MySQL 5.7 C API Developer Guide :: 5.4.77 mysql_store_result()

把查询到的结果转存到某个地方,MYSQL_RES


MYSQL_RES的内容其实就是一个结构体

mysql_num_rows() 

MySQL :: MySQL 5.7 C API Developer Guide :: 5.4.49 mysql_num_rows()

拿取行 

mysql_num_fields()

MySQL :: MySQL 5.7 C API Developer Guide :: 5.4.48 mysql_num_fields()

拿取列 

 

其中 my_ulonglong 其实就是 unsigned long long 类型的数据

 

测试4:行列获取测试
#include <iostream>
#include <unistd.h>
#include <string>
#include <mysql/mysql.h>

// const std::string host = "127.0.0.1";
const std::string host = "localhost";   // 使用本地回环也可以
const std::string user = "connector";
const std::string passwd = "123456";
const std::string db = "conn";
const unsigned int port = 8080;

int main()
{
    // std::cout << "mysql client version: " << mysql_get_client_info() << std::endl;

    // 创建一个mysql句柄
    MYSQL *my = mysql_init(nullptr);
    if(nullptr == my)
    {
        std::cerr << "init MySQL error" << std::endl;
        return 1;
    }
    if(mysql_real_connect(my, host.c_str(), user.c_str(), passwd.c_str(), db.c_str(), port, nullptr, 0) == nullptr)
    {
        std::cerr << "connect MySQL error" << std::endl;
        return 2;
    }
    mysql_set_character_set(my, "utf8");

    // std::string sql = "update user set name='Jimmy' where id=2"; // 改
    // std::string sql = "insert into user (name, age, telphone) values ('peter', 19, '987654321')";
    // std::string sql = "delete from user where id=4";
    // std::string sql = "insert into user (name, age, telphone) values ('张三', 19, '666666666')";

    std::string sql = "select * from user";
    int n = mysql_query(my, sql.c_str());
    if(n == 0) std::cout << sql << " success: " << n << std::endl;
    else 
    {
        std::cerr << sql << " failed: " << n << std::endl;
        return 3;
    }
    MYSQL_RES *res = mysql_store_result(my);
    if(nullptr == res)
    {
        std::cerr << "mysql_store_result error" << std::endl;
        return 4;
    }

    my_ulonglong rows = mysql_num_rows(res); // 拿取行
    my_ulonglong fields = mysql_num_fields(res); // 拿取列

    std::cout << "行: " << rows << std::endl;
    std::cout << "列: " << fields << std::endl;

    /*
    // 其实我们并不需要这么麻烦去写一个MySQL的客户端,我们只需要使用即可
    std::string sql;
    while(true)
    {
        std::cout << "MySQL>>> ";
        if(!std::getline(std::cin, sql) || sql == "quit")
        {
            std::cout << "bye bye" << std::endl;
            break;
        }
        int n = mysql_query(my, sql.c_str());
        if(n == 0)
        {
            std::cout << sql << " success: " << n << std::endl;
        }
        else
        {
            std::cerr << sql << " failed: " << n << std::endl;
        }
    }
    */
    // sleep(10);
    // std::cout << "connnect success" << std::endl;
    // 关闭释放该句柄
    mysql_close(my);
    return 0;
}

看到结果,我们确实拿到了具体的行和列 

当我们测试拿取一条数据的时候,也是正确的,用where进行筛选

mysql_fetch_row()

MySQL :: MySQL 5.7 C API Developer Guide :: 5.4.21 mysql_fetch_row()

自动迭代遍历,获取数据

一个新的宏,MYSQL_ROW ,其实就是一个指针,我们将其看做一个指向一个二维数组的指针就行了

测试5:读取数据测试
#include <iostream>
#include <unistd.h>
#include <string>
#include <mysql/mysql.h>

// const std::string host = "127.0.0.1";
const std::string host = "localhost";   // 使用本地回环也可以
const std::string user = "connector";
const std::string passwd = "123456";
const std::string db = "conn";
const unsigned int port = 8080;

int main()
{
    // std::cout << "mysql client version: " << mysql_get_client_info() << std::endl;

    // 创建一个mysql句柄
    MYSQL *my = mysql_init(nullptr);
    if(nullptr == my)
    {
        std::cerr << "init MySQL error" << std::endl;
        return 1;
    }
    if(mysql_real_connect(my, host.c_str(), user.c_str(), passwd.c_str(), db.c_str(), port, nullptr, 0) == nullptr)
    {
        std::cerr << "connect MySQL error" << std::endl;
        return 2;
    }
    mysql_set_character_set(my, "utf8");

    // std::string sql = "update user set name='Jimmy' where id=2"; // 改
    // std::string sql = "insert into user (name, age, telphone) values ('peter', 19, '987654321')";
    // std::string sql = "delete from user where id=4";
    // std::string sql = "insert into user (name, age, telphone) values ('张三', 19, '666666666')";
    // std::string sql = "select * from user where id=3";
    std::string sql = "select * from user";
    int n = mysql_query(my, sql.c_str());
    if(n == 0) std::cout << sql << " success: " << n << std::endl;
    else 
    {
        std::cerr << sql << " failed: " << n << std::endl;
        return 3;
    }
    MYSQL_RES *res = mysql_store_result(my);
    if(nullptr == res)
    {
        std::cerr << "mysql_store_result error" << std::endl;
        return 4;
    }

    // 到这里都是和结果集有关的,MYSQL_RES
    my_ulonglong rows = mysql_num_rows(res); // 拿取行
    my_ulonglong fields = mysql_num_fields(res); // 拿取列

    std::cout << "行: " << rows << std::endl;
    std::cout << "列: " << fields << std::endl;

    // 将其当作一个二维数组去遍历即可
    for(my_ulonglong i = 0; i < rows; ++i)
    {
       MYSQL_ROW row = mysql_fetch_row(res);    // 和迭代器很像,会自己维护一个指针,自动遍历
       for(my_ulonglong j = 0; j < fields; ++j)
       {
            std::cout << row[j] << "\t"; // *(row+j) 其实就是解引用
       }
       std::cout << std::endl;
    }

    /*
    // 其实我们并不需要这么麻烦去写一个MySQL的客户端,我们只需要使用即可
    std::string sql;
    while(true)
    {
        std::cout << "MySQL>>> ";
        if(!std::getline(std::cin, sql) || sql == "quit")
        {
            std::cout << "bye bye" << std::endl;
            break;
        }
        int n = mysql_query(my, sql.c_str());
        if(n == 0)
        {
            std::cout << sql << " success: " << n << std::endl;
        }
        else
        {
            std::cerr << sql << " failed: " << n << std::endl;
        }
    }
    */
    // sleep(10);
    // std::cout << "connnect success" << std::endl;
    // 关闭释放该句柄
    mysql_close(my);
    return 0;
}

可以看到我们拿取到了结果,并且没有错误

mysql_fetch_fields()

MySQL :: MySQL 5.7 C API Developer Guide :: 5.4.19 mysql_fetch_fields()

获取列名信息 

 

MYSQL_FIELD

这里是不是很熟悉,这里就是MySQL里面的那一套 

 

 

测试6:读取数据测试

#include <iostream>
#include <unistd.h>
#include <string>
#include <mysql/mysql.h>

// const std::string host = "127.0.0.1";
const std::string host = "localhost";   // 使用本地回环也可以
const std::string user = "connector";
const std::string passwd = "123456";
const std::string db = "conn";
const unsigned int port = 8080;

int main()
{
    // std::cout << "mysql client version: " << mysql_get_client_info() << std::endl;

    // 创建一个mysql句柄
    MYSQL *my = mysql_init(nullptr);
    if(nullptr == my)
    {
        std::cerr << "init MySQL error" << std::endl;
        return 1;
    }
    if(mysql_real_connect(my, host.c_str(), user.c_str(), passwd.c_str(), db.c_str(), port, nullptr, 0) == nullptr)
    {
        std::cerr << "connect MySQL error" << std::endl;
        return 2;
    }
    mysql_set_character_set(my, "utf8");

    // std::string sql = "update user set name='Jimmy' where id=2"; // 改
    // std::string sql = "insert into user (name, age, telphone) values ('peter', 19, '987654321')";
    // std::string sql = "delete from user where id=4";
    // std::string sql = "insert into user (name, age, telphone) values ('张三', 19, '666666666')";
    // std::string sql = "select * from user where id=3";
    std::string sql = "select * from user";
    int n = mysql_query(my, sql.c_str());
    if(n == 0) std::cout << sql << " success: " << n << std::endl;
    else 
    {
        std::cerr << sql << " failed: " << n << std::endl;
        return 3;
    }
    MYSQL_RES *res = mysql_store_result(my);
    if(nullptr == res)
    {
        std::cerr << "mysql_store_result error" << std::endl;
        return 4;
    }

    // 到这里都是和结果集有关的,MYSQL_RES
    my_ulonglong rows = mysql_num_rows(res); // 拿取行
    my_ulonglong fields = mysql_num_fields(res); // 拿取列

    std::cout << "行: " << rows << std::endl;
    std::cout << "列: " << fields << std::endl;

    // 将其当作一个二维数组去遍历即可
    // 读取属性
    MYSQL_FIELD *fields_arry = mysql_fetch_fields(res);
    for(my_ulonglong i = 0; i < fields; i++)
    {
        std::cout << fields_arry[i].name << "\t";
    }
    std::cout << "\n";

    // 读取内容
    for(my_ulonglong i = 0; i < rows; ++i)
    {
       MYSQL_ROW row = mysql_fetch_row(res);    // 和迭代器很像,会自己维护一个指针,自动遍历
       for(my_ulonglong j = 0; j < fields; ++j)
       {
            std::cout << row[j] << "\t"; // *(row+j) 其实就是解引用
       }
       std::cout << std::endl;
    }

    // 读取数据库名,表名
    std::cout << fields_arry[0].db << " " << fields_arry[0].table << std::endl;

    /*
    // 其实我们并不需要这么麻烦去写一个MySQL的客户端,我们只需要使用即可
    std::string sql;
    while(true)
    {
        std::cout << "MySQL>>> ";
        if(!std::getline(std::cin, sql) || sql == "quit")
        {
            std::cout << "bye bye" << std::endl;
            break;
        }
        int n = mysql_query(my, sql.c_str());
        if(n == 0)
        {
            std::cout << sql << " success: " << n << std::endl;
        }
        else
        {
            std::cerr << sql << " failed: " << n << std::endl;
        }
    }
    */
    // sleep(10);
    // std::cout << "connnect success" << std::endl;
    // 关闭释放该句柄
    mysql_close(my);
    return 0;
}

我们可以看到,其实MySQL的客户端本质上就是对这些数据进行处理,本身就是看做对字符串的处理,原理很简单

mysql_free_result()

MySQL :: MySQL 5.7 C API Developer Guide :: 5.4.25 mysql_free_result()

释放结果集 

官方提供了专门用来释放结果集的函数

使用起来也很简单,就像C++里面的free函数一样就行 

mysql_free_result(res);

补充2:事务

我们都知道每一次的单SQL语句在MySQL看来都是一个事务,所以我们这里并没有测试事务的启动和提交,我们知道这一点就行了,通常我们会把一堆SQL语句放一起提交,那么MySQL就会把它当成一个事务,所以我们在代码上一般也不怎么讨论事务的启动和提交,当然了我们也可以开启事务,MySQL也提供了相应的函数比如下面这几个

my_bool STDCALL mysql_autocommit(MYSQL * mysql, my_bool auto_mode);
my_bool STDCALL mysql_commit(MYSQL * mysql);
my_bool STDCALL mysql_rollback(MYSQL * mysql);

其实我们也可以用mysql_query()这个提交来开启事务,比如提交begin,commit,rollback都能够实现,看自己需求

全部的测试代码

#include <iostream>
#include <unistd.h>
#include <string>
#include <mysql/mysql.h>

// const std::string host = "127.0.0.1";
const std::string host = "localhost";   // 使用本地回环也可以
const std::string user = "connector";
const std::string passwd = "123456";
const std::string db = "conn";
const unsigned int port = 8080;

int main()
{
    // std::cout << "mysql client version: " << mysql_get_client_info() << std::endl;

    // 创建一个mysql句柄
    MYSQL *my = mysql_init(nullptr);
    if(nullptr == my)
    {
        std::cerr << "init MySQL error" << std::endl;
        return 1;
    }
    if(mysql_real_connect(my, host.c_str(), user.c_str(), passwd.c_str(), db.c_str(), port, nullptr, 0) == nullptr)
    {
        std::cerr << "connect MySQL error" << std::endl;
        return 2;
    }
    mysql_set_character_set(my, "utf8");

    // std::string sql = "update user set name='Jimmy' where id=2"; // 改
    // std::string sql = "insert into user (name, age, telphone) values ('peter', 19, '987654321')";
    // std::string sql = "delete from user where id=4";
    // std::string sql = "insert into user (name, age, telphone) values ('张三', 19, '666666666')";
    // std::string sql = "select * from user where id=3";
    std::string sql = "select * from user";
    int n = mysql_query(my, sql.c_str());
    if(n == 0) std::cout << sql << " success: " << n << std::endl;
    else 
    {
        std::cerr << sql << " failed: " << n << std::endl;
        return 3;
    }
    MYSQL_RES *res = mysql_store_result(my);
    if(nullptr == res)
    {
        std::cerr << "mysql_store_result error" << std::endl;
        return 4;
    }

    // 到这里都是和结果集有关的,MYSQL_RES
    my_ulonglong rows = mysql_num_rows(res); // 拿取行
    my_ulonglong fields = mysql_num_fields(res); // 拿取列

    std::cout << "行: " << rows << std::endl;
    std::cout << "列: " << fields << std::endl;

    // 将其当作一个二维数组去遍历即可
    // 读取属性
    MYSQL_FIELD *fields_arry = mysql_fetch_fields(res);
    for(my_ulonglong i = 0; i < fields; i++)
    {
        std::cout << fields_arry[i].name << "\t";
    }
    std::cout << "\n";

    // 读取内容
    for(my_ulonglong i = 0; i < rows; ++i)
    {
       MYSQL_ROW row = mysql_fetch_row(res);    // 和迭代器很像,会自己维护一个指针,自动遍历
       for(my_ulonglong j = 0; j < fields; ++j)
       {
            std::cout << row[j] << "\t"; // *(row+j) 其实就是解引用
       }
       std::cout << std::endl;
    }

    // 读取数据库名,表名
    std::cout << fields_arry[0].db << " " << fields_arry[0].table << std::endl;

    /*
    // 其实我们并不需要这么麻烦去写一个MySQL的客户端,我们只需要使用即可
    std::string sql;
    while(true)
    {
        std::cout << "MySQL>>> ";
        if(!std::getline(std::cin, sql) || sql == "quit")
        {
            std::cout << "bye bye" << std::endl;
            break;
        }
        int n = mysql_query(my, sql.c_str());
        if(n == 0)
        {
            std::cout << sql << " success: " << n << std::endl;
        }
        else
        {
            std::cerr << sql << " failed: " << n << std::endl;
        }
    }
    */
    // sleep(10);
    // std::cout << "connnect success" << std::endl;
    // 关闭释放该句柄
    mysql_free_result(res);
    mysql_close(my);
    return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1988473.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

vxe-table树形结构使用setCheckboxRow卡顿--已解决

项目场景&#xff1a; vxe-table树形结构使用setCheckboxRow进行部分节点选中 问题描述 vxe-table树形结构使用setCheckboxRow&#xff0c;在数据较多时卡顿 原因分析&#xff1a; setCheckboxRow内部进行了多次的循环遍历&#xff0c;导致速度慢 解决方案&#xff1a; …

YoloV9改进策略:Block改进|GroupMamba在RepNCSP模块中的革新应用|即插即用

在深度学习和计算机视觉领域&#xff0c;YoloV9以其卓越的性能和高效的检测能力赢得了广泛认可。为了进一步提升YoloV9的性能&#xff0c;我们创新性地引入了GroupMambaLayer作为其RepNCSP模块的核心改进。这一策略不仅显著增强了模型的性能&#xff0c;还优化了参数效率和计算…

[数据集][目标检测]轴承缺陷划痕检测数据集VOC+YOLO格式1166张1类别

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;1166 标注数量(xml文件个数)&#xff1a;1166 标注数量(txt文件个数)&#xff1a;1166 标注…

从 Pandas 到 Polars 四十五:Polars、Altair 和 Vegafusion

Altair长期以来一直是我最喜欢的可视化库。它允许我通过简洁且一致的API制作美丽的可视化图表。然而&#xff0c;去年我发现我无法将Polars的DataFrame传递给Altair图表时&#xff0c;我感到很失望。 但那些日子已经过去了。在这篇文章中&#xff0c;我们将探讨随着Altair 5的…

雷达气象学(1)——雷达电磁波的散射

文章目录 1.0 电磁波的特征1.1 散射的概念及类型1.2 散射函数——表示粒子的散射能力1.3 瑞利后向散射函数1.4 后向散射截面——更好地表示粒子的散射能力1.5 反射率因子 1.0 电磁波的特征 雷达的探测方式为电磁波。电磁波是在空间传播的电场和磁场两者结合&#xff0c;它在时…

C++从入门到起飞之——string类的模拟实现 全方位剖析!

&#x1f308;个人主页&#xff1a;秋风起&#xff0c;再归来~&#x1f525;系列专栏&#xff1a;C从入门到起飞 &#x1f516;克心守己&#xff0c;律己则安 目录 1、多文件之间的关系 2、模拟实现常用的构造函数 2.1 无参构造函数 2.2 有参的构造函数 2.3 析构函…

应急响应-主机安全之文件相关命令(Linux操作系统)

目录 概述常用命令file-探测给定文件的类型选项常用选项组合 stat-查看文件信息find-不止查找文件选项测试操作常用选项 locate-比find好用的查找命令选项常用选项组合 chmod-修改文件权限suidsbit chown、chgrp 修改文件所有者/所在组umask-显示或设置创建文件的权限掩码常用选…

理解Spring框架4:事务

理解Spring框架4&#xff1a;事务 (qq.com)

等保密评整改应该申请哪种SSL证书

在等保&#xff08;信息安全等级保护&#xff09;和密评&#xff08;商用密码应用安全性评估&#xff09;整改过程中&#xff0c;申请SSL证书是提升系统安全性的重要环节。下面是等保密评应该申请什么样证书的详细建议 类型选择 1 选择国密或者双算法证书 应优先考虑使用采用…

揭秘新型安卓间谍软件LianSpy的攻击手段

自2021年起&#xff0c;俄罗斯用户已成为一种新型未被记录的安卓后门间谍软件“LianSpy”的攻击目标。 网络安全公司卡巴斯基在2024年3月发现了这款恶意软件&#xff0c;并指出其利用俄罗斯的云服务Yandex Cloud进行命令和控制&#xff08;C2&#xff09;通信&#xff0c;以避免…

2024高中生必备物品有哪些?快收下这份必备物品清单!

随着新学期的脚步临近&#xff0c;为确保学习和生活都能顺利进行&#xff0c;挑选一些实用且高效的好物是非常重要的。在如今的数字化时代下&#xff0c;即使是学生&#xff0c;仍需要一系列智能电子产品&#xff0c;这些产品不仅能够提升学习效率&#xff0c;也能让学生党们的…

声明式UI语法

一、ArkTS的基本组成 Entry // 装饰器 Component // 装饰器 struct Hello { // 自定义组件State myText: string World;build() { // UI描述Column() { // 系统组件Text(Hello ${this.myText}).fontSize(50)Divider()Button(Click me).onClick(() > { // 事件方法t…

一次性讲清AI外呼系统,再也不用人工打电话

相信大家都有了解现在接到的机器人电话越来越多&#xff0c;那么真正操作机器人代替人工打电话其实很简单&#xff0c;学会了自然是节省大量人工拨打电话的时间 为什么电销要用外呼系统|||在现代科技的迅猛发展中&#xff0c;AI机器人已逐渐在各行各业崭露头角&#xff0c;与传…

022_java.lang.ThreadLocal

ThreadLocal使用案例 在并发编程中有时候需要让线程互相协作&#xff0c;而协作可以使用共享数据的方式来实现。针对共享数据的操作就需要锁机制来控制并发行为。锁虽好&#xff0c;但是毕竟会在一定程度上让线程之间互相阻塞。前辈们认为在线程需要互相协作的前提下&#xff…

服务器测试之RAID知识梳理

最近开始整理RAID卡相关规格信息&#xff0c;所以再重新汇总整理一下RAID相关的知识点及细节&#xff0c;尽量写的详细简单使用图示让大家更好理解 1.什么是Raid&#xff1f; RAID 是英文 Redundant Array of Independent Disks 的缩写&#xff0c;中文简称为独立磁盘冗余阵列…

Nuxt3所有页面使用服务端渲染需要注意些什么?

其实服务端渲染很多时候并不是所有页面都需要使用的&#xff0c;但是如果有些项目真的需要所有页面都使用服务端渲染&#xff0c;此时服务器压力很大&#xff0c;那要如何处理更好呢&#xff1f; 一、是否所有页面都需要使用服务端渲染呢&#xff1f; 大家可参考以下这篇文…

【深度学习】基于YOLOV5模型的图像识别-目标检测的性能指标详解与计算方法

目标检测是计算机视觉中的重要任务&#xff0c;主要目的是在图像中识别并定位特定的物体。YOLO&#xff08;You Only Look Once&#xff09;系列模型作为目标检测领域的代表性方法之一&#xff0c;凭借其高效和准确的特点&#xff0c;广泛应用于实际场景中。本文通过详细介绍目…

三十一、【人工智能】【机器学习】- 自编码器 (Autoencoders)

系列文章目录 第一章 【机器学习】初识机器学习 第二章 【机器学习】【监督学习】- 逻辑回归算法 (Logistic Regression) 第三章 【机器学习】【监督学习】- 支持向量机 (SVM) 第四章【机器学习】【监督学习】- K-近邻算法 (K-NN) 第五章【机器学习】【监督学习】- 决策树…

趣测系统源码获取,搭建系统详细教程,流量主+佣金+图文+挂载

一、趣测系统是什么&#xff1f; 趣测系统是一款集合了多种趣味测试的应用软件或小程序&#xff0c;以其独特的玩法和广泛的测试种类&#xff0c;为用户提供了全新的娱乐体验。该系统涵盖了心理测试、星座测试、性格测试、能力测试&#xff08;如IQ、EQ&#xff09;、情感测试…

数据结构(5.5_1)——哈夫曼树

带权路径长度&#xff1a; 结点的权 有某种现实含义的数值(如表示结点的重要性等) 结点的带权路径长度 从树的根到该结点的路径长度(经过的边数)与该结点上权值的乘积 树的带权路径长度 树中所有的叶结点的带权路径长度之和(WPL,Weighted Path Length) 哈夫曼树的定义&…