MySQL 使用C语言

news2024/9/21 22:42:37

一般使用MySQL很少用命令行,一般都是通过程序内部使用,MySQL也为不同的语言定制了不同的头文件和库函数,可以在自己的程序中通过包含头文件和编译时候链接库函数来使用MySQL。

现在一般安装MySQL的时候就会自动给你安装库函数和头文件。

可以自行通过以下命令查看。

查看库函数                          ls /usr/lib64/mysql

 查看头文件                        ls /usr/include/mysql

 如果没有的话,可以通过以下命令来安装。

安装开发库                         yum install -y mysql-community-devel

然后使用mysql的话,就通过包含头文件以及链接库函数来使用。

包含头文件                      #include<mysql.h> / #include<mysql/mysql.h> 

包含的头文件都是 mysql.h ,但是左边这种方式由于没有指定目录,因此在编译的时候需要添加指定路径

编译链接             

没指定路径:g++ -o test test.cc -I/include/mysql -L/lib64/mysql -lmysqlclient

指定路径:   g++ -o test test.cc  -L/lib64/mysql -lmysqlclient

-I : 这里的 I 是 i 的大写,表明指定头文件的目录

-L : 表明库文件的路径

-l : 这里的 l 是 L 的小写,表明链接的库文件

如果指定了头文件的路径,编译的时候就只需要链接库了。 

MySQL接口介绍

mysql_init()

想要使用一个数据库,必须先初始化。

 通过该函数可以创建一个MYSQL句柄,用来后续操作,传递的值可以为空。

mysql_real_connect()

该函数是通过 init 函数创建的句柄,来和特定的数据库进行连接。

失败返回NULL,成功则返回传入的句柄。

需要指定host,用户,密码,数据库,端口号,最后两个参数可以采用默认,直接填 nullptr 和 0 即可。

 mysql_query()

该函数可以用以下达对应的命令,如 select,insert 之类的语句。

返回值为0表示成功,否则表示失败。

下面做一个实验,来一一试试上面的函数和语句。

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

using namespace std;

const string host = "localhost";
const string user = "lbx";
const string password = "124533lbxLBX..";
const string db = "rootDB";
const unsigned int port = 3306;

int main()
{
    MYSQL * my;
    my = mysql_init(nullptr);
    if(my != NULL) cout<<"mysql init successed"<<endl;
    else cout<<"muysql init failed!"<<endl;

    if(mysql_real_connect(my,host.c_str(),user.c_str(),password.c_str(),db.c_str(),port,nullptr,0))
    cout<<"mysql connect successed !"<<endl;
    else cout<<"mysql connect failed !"<<endl;


    // string sql = "insert into test (name,age) values ('tom',12)";
    // string sqp = "delete from test where id = 2";
    // string sql = "update test set name='jack' where id=1";
    string sql = "select * from test";
    if(mysql_query(my,sql.c_str())) cout<<"mysql insert failed!"<<endl;
    else cout<<"mysql insert successed!"<<endl;

    mysql_close(my);
    return 0;
}

发现实验结果确实如预想的那样。

但是有个问题!select语句在这里没有现象,需要配合其他函数使用。

注意:有些版本的mysql在远程连接使用的时候,插入数据有中文字符的时候,可能会出现乱码,我这里的版本是 8.0的,因此没有问题,不过如果插入的数据有乱码时,可以通过

int mysql_set_character_set(MYSQL* mysql,  const char* csname)来设置字符集为utf8

 mysql_store_result

针对select语句需要输出或者查看内容的情况,mysql提供该函数来将select 的数据从mysql句柄中提取到 MYSQL_RES 中,然后再输出。

MYSQL_RES 是一个MySQL的一种结构体,能够保存存储在 MYSQL 类型变量中的数据。

不过这个函数的返回值是一个指针,因此肯定在程序中开辟了一块空间,这块空间需要手动释放。

MySQL提供函数用于释放该指针

mysql_free_result()

该函数是专门用来释放MYSQL_RES指针的空间的。 

 如何查看MYSQL_RES中的数据

实际上MYSQL_RES和MYSQL类型一样,都是一个句柄。

因此是无法直接从MYSQL_RES中直接读取数据的,因此MySQL还提供了其他几个函数配合提取数据。

mysql_num_rows()

该函数能够从 MYSQL_RES 中提取数据的行数。 

mysql_num_fields() 

该函数能够从 MYSQL_RES 中提取数据的列数。 

mysql_fetch_fields() 

该函数能够一次性获取所有列名,其返回值类似于一个数组指针,想访问其内容可以采用访问数组指针内容的方式。 

 

 不过 MYSQL_FIELD 本身是一个类,想获取列名还需要知道该类有什么样的成员。

我们可以直接查看该类的成员结构。

 其中列名分为列名和原列名,表明也是。这是因为select查询语句可以对列名进行重命名,因此会出现两个类似的变量。

mysql_fetch_row()

该函数能够获取结果内容,即每一行的内容。

而返回值的 MYSQL_ROW 类型实际上就是一个 char** 类型,因为接受的数据都是以字符串的形式接受的,因此想读取一行的数据,也是当作是一个二维数组来直接操作。

 实验

我们写下如下的代码来实验是否能够得到 select 的数据。

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

using namespace std;

const string host = "localhost";
const string user = "lbx";
const string password = "124533lbxLBX..";
const string db = "rootDB";
const unsigned int port = 3306;

int main()
{
    MYSQL * my;
    my = mysql_init(nullptr);
    if(my != NULL) cout<<"mysql init successed"<<endl;
    else cout<<"muysql init failed!"<<endl;

    if(mysql_real_connect(my,host.c_str(),user.c_str(),password.c_str(),db.c_str(),port,nullptr,0))
    cout<<"mysql connect successed !"<<endl;
    else cout<<"mysql connect failed !"<<endl;


    // string sql = "insert into test (name,age) values ('张三',12)";
    // string sqp = "delete from test where id = 2";
    // string sql = "update test set name='jack' where id=1";
    string sql = "select * from test";
    if(mysql_query(my,sql.c_str())) cout<<"mysql select failed!"<<endl;
    else cout<<"mysql select successed!"<<endl;

    //将数据从my中提取到res中
    MYSQL_RES* res = mysql_store_result(my);
    //获取数据的行数
    my_ulonglong row = mysql_num_rows(res);
    //获取数据的列数
    unsigned int col = mysql_num_fields(res);
    //获取数据的名称
    MYSQL_FIELD* file_name = mysql_fetch_fields(res);
    
    //输出列名
    for(int i = 0; i < col; i++)
    {
        cout<<file_name[i].name<<"\t";
    }
    cout<<endl;
    MYSQL_ROW line;
    for(int i = 0; i < row; i++)
    {
        //获取一行的数据
        line = mysql_fetch_row(res);
        // cout<<line[0]<<"\t"<<line[1]<<"\t"<<line[2]<<"\t";
        for(int j = 0; j < col; j++)
        {
            cout<<line[j]<<"\t";
        }
        cout<<endl;
    }
    mysql_close(my);
    return 0;
}

发现确实成功获得了数据。

此外。,有一个细节。

 

在这里,我们每次都是直接通过 mysql_fetch_row 来获取一行数据,没有说我们要获得哪一行的数据,但是结果却是正确的结果。

这是因为 res 就类似一个缓冲区,每通过 mysql_fetch_row 获取一行数据时,都会将提取出去的一行数据给删除,因此可以直接获取。

其他的函数

我们当然可以通过C语言链接来做类似于事务的操作。

首先我们可以通过 mysql_query() 来执行启动事务。

 

mysql_autocommit()

该函数用于启动事务。

这个函数可以开始事务是否自动提交。

我们可以通过 mode 参数来设置是否开启自动提交。

1 表示启动自动提交,0表示关闭自动提交。

mysql_commit()

 当启动一个事务可以通过该函数直接提交。

0 表示提交成功,其他表示失败

mysql_rollback()

该函数能够回滚事务。

 

0表示回滚成功, 其他表示失败。 

总结 

本文总结了C/C++如何连接mysql,然后也介绍了连接的函数以及一些注意事项,也介绍了select时的特殊情况所用的函数,并进行了实践,希望对各位有所帮助。

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

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

相关文章

python爬虫------- Selenium下篇(二十三天)

&#x1f388;&#x1f388;作者主页&#xff1a; 喔的嘛呀&#x1f388;&#x1f388; &#x1f388;&#x1f388;所属专栏&#xff1a;python爬虫学习&#x1f388;&#x1f388; ✨✨谢谢大家捧场&#xff0c;祝屏幕前的小伙伴们每天都有好运相伴左右&#xff0c;一定要天天…

11.哀家要长脑子了!

目录 1.453. 最小操作次数使数组元素相等 - 力扣&#xff08;LeetCode&#xff09; 2.665. 非递减数列 - 力扣&#xff08;LeetCode&#xff09; 3. 283. 移动零 - 力扣&#xff08;LeetCode&#xff09; 4. 3114. 替换字符可以得到的最晚时间 - 力扣&#xff08;LeetCode…

构建第一个ArkTS用的资源分类与访问

应用开发过程中&#xff0c;经常需要用到颜色、字体、间距、图片等资源&#xff0c;在不同的设备或配置中&#xff0c;这些资源的值可能不同。 应用资源&#xff1a;借助资源文件能力&#xff0c;开发者在应用中自定义资源&#xff0c;自行管理这些资源在不同的设备或配置中的表…

Redis实现延迟任务的几种方案

&#x1f3f7;️个人主页&#xff1a;牵着猫散步的鼠鼠 &#x1f3f7;️系列专栏&#xff1a;Java全栈-专栏 &#x1f3f7;️个人学习笔记&#xff0c;若有缺误&#xff0c;欢迎评论区指正 目录 1.前言 2.Redis如何实现延迟任务&#xff1f; 3.代码实现 3.1. 过期键通知事…

【Java】maven的生命周期和概念图

maven的生命周期&#xff1a; 在maven中存在三套"生命周期"&#xff0c;每一套生命周期,相互独立,互不影响的,但是中同一套生命周期里,执行后面的命令会自动先执行前面的命令 CleanLifeCycle&#xff1a;清理的生命周期 clean defaultLifeCycle&#xff1a;默认的…

智能物联网远传冷水表管理系统

智能物联网远传冷水表管理系统是一种基于物联网技术的先进系统&#xff0c;旨在实现对冷水表的远程监测、数据传输和智能化管理。本文将从系统特点、构成以及带来的效益三个方面展开介绍。 系统特点 1.远程监测&#xff1a;系统可以实现对冷水表数据的远程监测&#xff0c;无…

趣话最大割问题:花果山之群猴博弈

内容来源&#xff1a;量子前哨&#xff08;ID&#xff1a;Qforepost&#xff09; 编辑丨浪味仙 排版丨 沛贤 深度好文&#xff1a;3000字丨15分钟阅读 趋利避害&#xff0c;是所有生物遵循的自然法则&#xff0c;人类也不例外。 举个例子&#xff0c;假如你是某生鲜平台的配…

【Entity Framework】你要知道EF中功能序列与值转换

【Entity Framework】你要知道EF中功能序列与值转换 文章目录 【Entity Framework】你要知道EF中功能序列与值转换一、序列1.1 基本用法1.2 配置序列设置 二、值转换2.1 配置值转换器2.2 批量配置值转换器2.3 预定义的转换2.4 ValueConverter类2.5 内置转换器 三、应用3.1 简单…

Vue3基础笔记(3)高级绑定

一.Class绑定 数据绑定的一个常见需求场景师操纵元素的CSS class列表&#xff0c;因为class是attribute&#xff0c;我们可以和其他attribute一样使用v-bind将他们和动态的字符串绑定&#xff0c;但是在处理较为复杂的绑定时&#xff0c;拼接字符串容易出现错误。因此Vue专门为…

Python开源工具库使用之词云Wordcloud

文章目录 前言一、基本使用1.1 文本生成词云1.2 配置项 二、进阶用法2.1 自定义形状2.2 自定义着色2.3 自定义词频2.4 中文 三、实际案例3.1 工作报告词云3.2 周杰伦歌词词云 四、总结4.1 优点和局限性4.2 展望未来发展 参考 前言 当我们需要将大量文本数据可视化展示时&#…

为了执行SQL语句,MySQL的架构是怎样设计的

1. 把MySQL当个黑盒子一样执行SQL语句 上一讲我们已经说到&#xff0c;我们的系统采用数据库连接池的方式去并发访问数据库&#xff0c;然后数据库自己其实也会维护一个连 接池&#xff0c;其中管理了各种系统跟这台数据库服务器建立的所有连接 我们先看下图回顾一下 当我们的…

【PostmanJMeter】使用Postman和JMeter进行signature签名

一、前言 ​ 有些接口的请求会带上sign&#xff08;签名&#xff09;进行请求&#xff0c;各接口对sign的签名内容、方式可能不一样&#xff0c;但一般都是从接口的入参中选择部分内容组成一个字符串&#xff0c;然后再进行签名操作, 将结果赋值给sign; 完整规范的接口文档都会…

使用深度学习集成模型进行乳腺癌组织病理学图像分类

基于预训练的VGG16和VGG19架构训练了四种不同的模型&#xff08;即完全训练的 VGG16、微调的 VGG16、完全训练的 VGG19 和微调的 VGG19 模型&#xff09;。最初&#xff0c;我们对所有单独的模型进行了5倍交叉验证操作。然后&#xff0c;我们采用集成策略&#xff0c;取预测概率…

(一)C++自制植物大战僵尸集成开发环境安装

植物大战僵尸游戏开发教程专栏地址http://t.csdnimg.cn/uzrnw 1、下载Visual Studio集成开发环境 首先在微软官网下载Visual Studio 2022 Community版本。Community版本是免费的&#xff0c;并且满足个人开发的各种需求。Visual Studio 2022 下载链接&#xff1a;微软官网。选…

maven引入外部jar包

将jar包放入文件夹lib包中 pom文件 <dependency><groupId>com.jyx</groupId><artifactId>Spring-xxl</artifactId><version>1.0-SNAPSHOT</version><scope>system</scope><systemPath>${project.basedir}/lib/Spr…

[lesson33]C++中的字符串类

C中的字符串类 历史遗留问题 C语言不支持真正意义上的字符串C语言用字符数组和一组函数实现字符串操作C语言不支持自定义类型&#xff0c;因此无法获得字符串类型 解决方案 从C到C的进化过程引入自定义类型在C中可以通过类完成字符串类型的定义 标准库中的字符串类 C语言直…

蓝桥杯——玩具蛇

题目 小蓝有—条玩具蛇&#xff0c;一共有16节&#xff0c;上面标着数字1至16。每—节都是一个正方形的形状。相邻的两节可以成直线或者成90度角。 小蓝还有一个44的方格盒子&#xff0c;用于存放玩具蛇&#xff0c;盒子的方格上依次标着字母A到Р共16个字母。 小蓝可以折叠自…

什么是分组分析法

调查数据显示&#xff0c;2019 年年末中国大陆总人口 140005 万人。从年龄构成看&#xff0c;16 至 59 周岁年末人数为 89640 万&#xff0c;占总人口的比重为 64.0%&#xff1b;60 周岁及以上人口 25388 万人&#xff0c;占总人口的 18.1%&#xff0c;其中 65 周岁及以上人口 …

力扣LeetCode138. 复制带随机指针的链表 两种解法(C语言实现)

目录 题目链接 题目分析 题目定位&#xff1a; 解题思路 解题思路1&#xff08;粗暴但是复杂度高&#xff09; 解题思路2&#xff08;巧妙并且复杂度低&#xff09; 题目链接 138. 复制带随机指针的链表https://leetcode-cn.com/problems/copy-list-with-random-pointer/ …

OpenCV基本图像处理操作(一)——图像基本操作与形态学操作

环境配置地址 图像显示 import cv2 #opencv读取的格式是BGR import numpy as np import matplotlib.pyplot as plt#Matplotlib是RGB imgcv2.imread(cat.jpg) img_gray cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) img_gray.shape cv2.imshow("img_gray", img_gray) cv2…