MySQL数据库访问(C/C++)

  MySQL的访问者都属于客户端,如以上三种方式,这一期将要讲的是C/C++编程接口的访问。

        第三方库的准备:C/C++原生库并不提供连接MySQL的API接口,需要导入第三方库,不过通常都在下载MySQL服务时就下好了,只需要在编译时加上动态库链接和相应地址。如果没有库,使用以下指令安装:

代码语言:javascript

AI代码解释

yum install myaql-community-server

客户端初始化过程:

  1. 初始化mysql操作句柄
  2. 连接mysql服务器
  3. 设置客户端的字符集
  4. 选择想要操作的数据库
  5. 操作库(增删改查)
初始化句柄

句柄类似一个数据结构的地址,到时候用来找到MySQL的相关信息,类似FILE*。

代码示例:

代码语言:javascript

AI代码解释

MYSQL* mysql=mysql_init(nullptr);
连接mysql服务器

函数原型:

代码语言:javascript

AI代码解释

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 // 客户端标志
);

参数: 

  • mysql:mysql句柄,由 mysql_init() 初始化的连接句柄指针。
  • host:主机名 (如 "localhost"或"127.0.0.1")。
  • user:用户名,如果为NULL,表示使用当前登录用户名。
  • passwd:用户密码。如果为NULL,表示不使用密码。
  • db:要使用的默认数据库名称,可以为NULL。
  • port:mysql服务的端口号,如果为0,使用默认端口(3306)。
  • unix_socket:套接字路径,暂不关心,设置为NULL,表示使用默认套接字。
  • client_flag:标志位,很少用到,暂时不关系,设置为0即可。

返回值:

  • 成功:返回原来的mysql句柄。
  • 失败:返回nullptr。

代码示例:

代码语言:javascript

AI代码解释

#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
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;
}

在实际开发中最好不要用root用户访问。

设置客户端的字符集

        在连接数据库后要保持客户端与mysqld的字符集一致,要不然会出现乱码。通常都统一设为utf8。

代码示例:

代码语言:javascript

AI代码解释

mysql_set_character_set(mysql,"utf8");

实参mysql是由 mysql_init() 初始化的连接句柄指针。

选择需要操作的数据库

        在做连接时已经选好了现在就不用选,只是考虑到中途需要换其他库的情况。

代码语言:javascript

AI代码解释

mysql_select_db(mysql,"conn");

conn为一个准备好的数据库的库名。 

执行sql语句(增删改查)

使用

int mysql_query(MYSQL*, const char*)

 其中参数为mysql句柄和SQL语句,SQL语句以字符串的形式传入。成功返回0,否则返回非0。

以增为例,如下:

代码语言:javascript

AI代码解释

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;
}

        增删改都只要sql语句执行成功,数据库中的时间就发生改变了,没有反馈结果。而查询是不一样的,因为首先执行语句成功,结果在服务器里边,需要把它保存到本地进行访问。

数据查询流程:
  1. 使用sql语句查询成功后把查询结果保存到本地(获取结果集)
  2. 获取查询结果集的结果条数
  3. 遍历结果集
  4. 释放结果集的空间

数据查询结果是在服务器端的,我们需要把它保存到本地内存才能进行访问。使用

 MYSQL_RES* mysql_store_result(MYSQL*)

        返回值为MYSQL_RES*类型,是一个结构体类型的指针,里面保存了查询结果和相关属性。其中mysqld把所有查询结果都当做字符串类型给我们返回。我们可以把结果当做char* [ ][ ](或char** []),即储存char*的二维数组。

获取结果集,代码示例:

代码语言:javascript

AI代码解释

MYSQL_RES *res = mysql_store_result(mysql);
if (res == nullptr)
{
    std::cout << "mysql_store_result fail" << std::endl;
    return 1;
}

接下来要做的从res中获取结果即可,如果做呢?需要知道它的行和列然后进行遍历。

获取行数:

代码语言:javascript

AI代码解释

int row = mysql_num_rows(res);

获取列数:

代码语言:javascript

AI代码解释

int col = mysql_num_fields(res);

遍历并打印数据:

使用函数

        MYSQL_ROW mysql_fetch_row(MYSQL_RES*) 

获取单个行信息, result会记录每次遍历的到行。代码示例:

代码语言:javascript

AI代码解释

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提供的接口:

 void mysql_free_result(MYSQL_RES*)

释放MySQL操作句柄,使用函数: void mysql_close(MYSQL*);

即:

代码语言:javascript

AI代码解释

mysql_free_result(res);
mysql_close(mysql);

源码:

代码语言:javascript

AI代码解释

#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;
}

非常感谢您能耐心读完这篇文章。倘若您从中有所收获,还望多多支持呀!

全部评论

相关推荐

我是个没天赋的人,努力学习也只考上了个一本,家里条件也不怎么样。大一玩了一年,没怎么学技术,也没有卷绩点,全在游戏小说抖音中度过。大二上接触了牛客,看到了许多优秀的同龄人。很多双非的同学,甚至不少学院本的同学都进了大厂实习。我把他们作为榜样,决定好好学习。我每天都至少学八九个小时,很多次都想要放弃,想哭,我都坚持了下来。我总是告诉自己,只要努力,就一定能有好的结果。这几个月过的很累,但也很充实。转眼就到大二下了,我决定去找实习了,但是学校的认可度让我感到心底发凉,明明和广工这种知名双非分差不多,结果总被问是不是公办本科。两个月投了一千份实习,只有四个面试,最终去了个中小厂实习。结果就是改了两个月bug,虽然mt人挺好,但是实在学不了什么东西,所以就离职开始面试。凭借这段实习,确实多了不少中小厂面试,但是大厂依旧没有面试机会。除了字节腾讯所有大厂都投了,结果依旧是0面试。最终有幸获得美团的面试机会,面试也幸运的通过,然后入职了。为了省钱坐十几个小时硬座到北京,到北京的第一天,由于太激动想要租房,结果被坑了2600,之前实习的地方,房东也故意不退押金,加起来总共损失3000多。虽然很难过,但是我还是忍受了下来,我想着实习才刚开始,会好起来的。实习了大半个月,跟学校这边沟通一直不成功,我每天都寝食难安,精神都快崩溃了,经常凌晨两三点才睡着,想要跳楼。最后迫于无奈,我一大早我坐高铁回去,恳求院主任给我一个机会,我怎么恳求讲理都没用,甚至都磕头下跪了,还是没用。院主任一点机会都没给我,连让我跟各科老师沟通机会都不给,要不休学要不辞职。我没得选择,这段实习我看的比我的生命还重要,这不仅是我这大半年的心血,更是未来的一份希望。我只能休学,我想着现在好好实习,多学点技术,到时候秋招早点拿到offer,然后再补这学期的课也不是不行。但是,现实总是事与愿违。这三个月说实话并没有学到什么东西,前一个月很闲,这两个月事很多,每天基本都是九点后下班,但都是杂活。产出都是靠我看文档加上代码写上去的。我真的很想锻炼一下技术,但是总是不尽人意。三个月了,我到现在都还没做过一个像样点的需求。产出是能编,但有破绽不说还没锻炼到技术。我好想真正的做一下需求啊,我好想真正的走完一遍流程,去上线一次啊。接下来两个月,我不知道该怎么坚持下去了,现在每天都想哭,很焦虑,很难受。冒着将来可能延毕的风险,我赌上了一切,结果输的这么彻底,可能我就只是个小丑吧。如果家庭好点就不用卷了,如果我聪明一点就能上个好学校了,如果大一有人带我,我就不会摆烂了,如果院主任给我个机会,我就不用这么苦了,如果我实习能有机会好好锻炼自己,我就不用这么难受焦虑了。但是没办法,我又能怎么办呢,无非是咬紧牙关罢了,毕竟没人能够帮助我,只能靠自己我可真是个小丑啊
牛客57762807...:这种院长就是恶心的死,家里户口本只有一页的孤儿,我们院长也是,家里人都去亲自找院长,送几百块的水果,送礼物,结果还是被她一顿电话操作毁offer了,担心学生安全不放实习就算了,特么是担心上课没人去,我这种会容易带坏风气导致很多人效仿,***妈呢,什么时候学生的前途被一堆KPI数字给限制了,本来还想做个乖孩子的,以为院长能开开恩,但是这种死了没的东西让我决定我再也不做乖孩子了,后面才知道爱哭的孩子没有奶吃的,还会被一顿毒打,大三下学期我决定偷偷溜走一学期,一节课都不去,少的钱她一个孤儿也给我补不了
投递美团等公司10个岗位
点赞 评论 收藏
分享
不愿透露姓名的神秘牛友
11-20 10:05
点赞 评论 收藏
分享
11-20 10:36
南昌大学 Java
牛客99209674...:怎么可能,今年互联网比去年行情好很多,jd和美团大战,一下子多招多少人呢
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务