linux下使用C语言操作MYSQL数据库(API使用libmysqlclient-dev)

2023-11-13


运行环境

Ubuntu20.04 虚拟机
Mysql 8.0 API libmysqlclient-dev
gcc 9.4.0


一、准备工作

1、在Ubuntu上准备mysql开发环境

更新软件源

sudo apt update

安装libmysqlclient-dev,这个lib库是Linux下C/C++连接mysql的客户端,
关于libmysqlclient-dev接口与数据类型的介绍请见我的另一篇文章
-->https://blog.csdn.net/goosse/article/details/124287883

sudo apt install libmysqlclient-dev

2、创建测试数据库与表

创建一个名为C_DB的数据库,在库中建立一张名为C_TBL的表

CREATE DATABASE C_DB;
USE C_DB;
CREATE TABLE C_TBL(
ID INT PRIMARY KEY AUTO_INCREMENT,#主键且自增
NAME VARCHAR(32),
SEX VARCHAR(8)
);

二、建立与mysql的连接

1、在C文件中引入头文件

在C文件中引入头文件#inlude<mysql.h>
通过MYSQL mysql;创建一个mysql结构体对象
MYSQL结构体定义在mysql.h

#include<mysql.h>
#include<stdio.h>
#include<string.h>
int main()
{
	 MYSQL mysql;
}

2、初始化mysql与数据库的通道

mysql_init函数初始化失败会返回NULL
mysql_error是mysql API提供的标准错误

	 if(mysql_init(&mysql) == NULL)
    {
        printf("%s",mysql_error(&mysql));
        return -1;
    }

3、与mysql建立真实连接

先在文件最前面定义一些宏,方便后面使用

#define C_DB_SERVER_IP   "192.168.186.128" //要连接的数据库IP
#define C_DB_SERVER_PORT 3306			   //要连接的端口号
#define C_DB_USERNAME    "admin"		   //mysql用户名
#define C_DB_PASSWORD    "admin"		   //mysql密码
#define C_DB_DEFAULT_DB  "C_DB"			   //连接后默认使用的数据库
	//参数依次为 mysql通道,
	//ip,用户名,
	//密码,数据库名,
	//端口号,socket(设置为NULL的时候表示不适用socket),客户端标识符
   	//mysql_real_connect函数若返回0表示则表示连接失败
    if(!mysql_real_connect(&mysql,
	C_DB_SERVER_IP, C_DB_USERNAME, 
    C_DB_PASSWORD, C_DB_DEFAULT_DB, 
    C_DB_SERVER_PORT,NULL, 0))
    {
        printf("mysql_real_connect : %s\n",mysql_error(&mysql));
        return -2;
    }

此时已经通过C代码与MYSQL数据库进行了连接,下一步便可以开始进行数据库的操作

三、添加操作(CRUD - C(CREATE))

定义一个添加数据用的函数int c_db_insert(MYSQL *mysql, char *sql)
第一个参数是传进来的mysql管道,第二个参数传进来要使用的sql语句

int c_db_insert(MYSQL *mysql, char *sql)
{
    if(mysql == NULL)
    {
        printf("%s",mysql_error(mysql));
        return -1;
    }
    //mysql_real_query是操作的关键 参数分别是 mysql管道,sql语句,sql语句长度
    //mysql_real_query 返回0表示成功
    if(mysql_real_query(mysql,sql,strlen(sql)))
    {
        printf("mysql_real_query : %s\n",mysql_error(mysql));
        return -2;
    }
    return 0;
}

四、查询操作(CRUD - R(REMOVE))

定义一个查询数据用的函数int c_db_select(MYSQL *mysql,char *sql)
第一个参数是传进来的mysql管道,第二个参数传进来要使用的sql语句

int c_db_select(MYSQL *mysql,char *sql)
{
    if(mysql == NULL)
    {
        printf("%s",mysql_error(mysql));
        return -1;
    }
    //mysql_real_query是操作的关键 参数分别是 mysql管道,sql语句,sql语句长度
    //mysql_real_query 返回0表示成功
    if(mysql_real_query(mysql,sql,strlen(sql)))
    {
        printf("mysql_real_query : %s\n",mysql_error(mysql));
        return -2;
    }

    //把查到的数据存储在内存中
    //mysql_store_result(mysql)会返回一个MYSQL_RES类型的指针,存储查询sql语句运行的结果
    MYSQL_RES *res = mysql_store_result(mysql);
    if(res == NULL)
    {
        printf("mysql_store_result : %s",mysql_error(mysql));
        return -3;
    }
    //获取列的个数
    int rows = mysql_num_rows(res);
    //获取行的个数
    int fields = mysql_num_fields(res);
    printf("rows = %d fields = %d\n", rows, fields);

    //把结果打印
    //mysql_fetch_row() 返回一个查询结果集的数组
    MYSQL_ROW row;
    while((row = mysql_fetch_row(res)))
    {
        int i = 0;
        for (int i = 0; i < fields; i++)
        {
            printf("%s\t",row[i]);
        }
        printf("\n");
    }
    return 0;
}

五、更改操作(CRUD - U(UPDATE))

定义一个查询数据用的函数int c_db_update(MYSQL *mysql,char *sql)
第一个参数是传进来的mysql管道,第二个参数传进来要使用的sql语句

int c_db_update(MYSQL *mysql,char *sql)
{
    if(mysql == NULL)
    {
        printf("%s",mysql_error(mysql));
        return -1;
    }
    //mysql_real_query是操作的关键 参数分别是 mysql管道,sql语句,sql语句长度
    //mysql_real_query 返回0表示成功
    if(mysql_real_query(mysql,sql,strlen(sql)))
    {
        printf("mysql_real_query : %s\n",mysql_error(mysql));
        return -2;
    }
    return 0;
}

六、删除操作(CRUD - D(DELETE))

在mysql8.0中,通过非主键删除数据会被认定为不安全的操作,所以此处引用mysql的存储过程,来实现通过NAME删除数据,其中SQL_SAFE_UPDATES用于调整安全级别

DELIMITER **
CREATE PROCEDURE PROC_DELETE_USER(IN UNAME VARCHAR(32))
BEGIN
SET SQL_SAFE_UPDATES=0;
DELETE from C_TBL WHERE NAME=UNAME;
SET SQL_SAFE_UPDATES=1;
END**

需要在对应MYSQL服务器中运行这些语句,在之后便可以通过CALL PROC_DELETE_USER(argv)的方式来调用此MYSQL服务器中的名字为 PROC_DELETE_USERPROCEDURE

定义一个查询数据用的函数int c_db_delete(MYSQL *mysql,char *sql)
第一个参数是传进来的mysql管道,第二个参数传进来要使用的sql语句

int c_db_delete(MYSQL *mysql,char *sql)
{
        if(mysql == NULL)
    {
        printf("%s",mysql_error(mysql));
        return -1;
    }
    //mysql_real_query 是操作的关键 参数分别是 mysql管道,sql语句,sql语句长度
    //mysql_real_query 返回0表示成功
    if(mysql_real_query(mysql,sql,strlen(sql)))
    {
        printf("mysql_real_query : %s\n",mysql_error(mysql));
        return -2;
    }
    return 0;
}

完整代码

#include<mysql.h>
#include<stdio.h>
#include<string.h>
#define C_DB_SERVER_IP   "192.168.186.128"
#define C_DB_SERVER_PORT 3306
#define C_DB_USERNAME    "admin"
#define C_DB_PASSWORD    "admin"
#define C_DB_DEFAULT_DB  "C_DB"

//插入
int c_db_insert(MYSQL *mysql, char *sql)
{
    if(mysql == NULL)
    {
        printf("%s",mysql_error(mysql));
        return -1;
    }
    if(mysql_real_query(mysql,sql,strlen(sql)))
    {
        printf("mysql_real_query : %s\n",mysql_error(mysql));
        return -2;
    }
    return 0;
}

//查询
int c_db_select(MYSQL *mysql,char *sql)
{
    if(mysql == NULL)
    {
        printf("%s",mysql_error(mysql));
        return -1;
    }
    //mysql_real_query是操作的关键 参数分别是 mysql管道,sql语句,sql语句长度
    //mysql_real_query 返回0表示成功
    if(mysql_real_query(mysql,sql,strlen(sql)))
    {
        printf("mysql_real_query : %s\n",mysql_error(mysql));
        return -2;
    }

    //把查到的数据存储在内存中
    //mysql_store_result(mysql)会返回一个MYSQL_RES类型的指针,存储查询sql语句运行的结果
    MYSQL_RES *res = mysql_store_result(mysql);
    if(res == NULL)
    {
        printf("mysql_store_result : %s",mysql_error(mysql));
        return -3;
    }
    //获取列的个数
    int rows = mysql_num_rows(res);
    //获取行的个数
    int fields = mysql_num_fields(res);
    printf("rows = %d fields = %d\n", rows, fields);

    //把结果打印
    //mysql_fetch_row() 返回一个查询结果集的数组
    MYSQL_ROW row;
    while((row = mysql_fetch_row(res)))
    {
        int i = 0;
        for (int i = 0; i < fields; i++)
        {
            printf("%s\t",row[i]);
        }
        printf("\n");
    }
    return 0;
}

//更新
int c_db_update(MYSQL *mysql,char *sql)
{
    if(mysql == NULL)
    {
        printf("%s",mysql_error(mysql));
        return -1;
    }
    //mysql_real_query是操作的关键 参数分别是 mysql管道,sql语句,sql语句长度
    //mysql_real_query 返回0表示成功
    if(mysql_real_query(mysql,sql,strlen(sql)))
    {
        printf("mysql_real_query : %s\n",mysql_error(mysql));
        return -2;
    }
    return 0;
}

//删除
int c_db_delete(MYSQL *mysql,char *sql)
{
        if(mysql == NULL)
    {
        printf("%s",mysql_error(mysql));
        return -1;
    }
    //mysql_real_query 是操作的关键 参数分别是 mysql管道,sql语句,sql语句长度
    //mysql_real_query 返回0表示成功
    if(mysql_real_query(mysql,sql,strlen(sql)))
    {
        printf("mysql_real_query : %s\n",mysql_error(mysql));
        return -2;
    }
    return 0;
}

int main()
{
	MYSQL mysql;
    if(mysql_init(&mysql) == NULL)
    {
        printf("mysql_init : %s\n",mysql_error(&mysql));
        return -1;
    }

    // mysql_real_connect 若返回0表示则表示连接失败
    if(!mysql_real_connect(&mysql,
	C_DB_SERVER_IP, C_DB_USERNAME, 
    C_DB_PASSWORD, C_DB_DEFAULT_DB, 
    C_DB_SERVER_PORT,NULL, 0))
    {
        printf("mysql_real_connect : %s\n",mysql_error(&mysql));
        return -2;
    } 

    //添加操作
    // char insert_sql[] = "INSERT C_TBL(NAME, SEX) VALUES('zhangsan','man')";
    // c_db_insert(&mysql,insert_sql);

    //查询操作
    // char select_sql[] = "SELECT * FROM C_TBL";
    // c_db_select(&mysql, select_sql);

    //更新操作
    // char update_sql[] = "UPDATE C_TBL SET NAME='lisi' WHERE ID='1'";
    // c_db_select(&mysql, update_sql);

    //删除操作
    // char delete_sql[] = "CALL PROC_DELETE_USER('zhangsan')";
    // c_db_select(&mysql, delete_sql);

    return 0;
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

linux下使用C语言操作MYSQL数据库(API使用libmysqlclient-dev) 的相关文章

  • Web 客户端和 Expect100Continue

    使用 WebClient C NET 时设置 Expect100Continue 的最佳方法是什么 我有下面的代码 我仍然在标题中看到 100 continue 愚蠢的 apache 仍然抱怨 505 错误 string url http
  • 查找c中结构元素的偏移量

    struct a struct b int i float j x struct c int k float l y z 谁能解释一下如何找到偏移量int k这样我们就可以找到地址int i Use offsetof 找到从开始处的偏移量z
  • Asp.NET WebApi 中类似文件名称的路由

    是否可以在 ASP NET Web API 路由配置中添加一条路由 以允许处理看起来有点像文件名的 URL 我尝试添加以下条目WebApiConfig Register 但这不起作用 使用 URIapi foo 0de7ebfa 3a55
  • 为什么当实例化新的游戏对象时,它没有向它们添加标签? [复制]

    这个问题在这里已经有答案了 using System Collections using System Collections Generic using UnityEngine public class Test MonoBehaviou
  • Apache 2 中的“捕获 SIGWINCH”错误是什么?

    我的服务器 ubuntu 8 04 LAMP运行drupal 6 当流量较高时 它会停止提供页面 重新启动apache2将不起作用 所以我必须重新启动该服务 我在 apache2 error log 中找到了这条消息 通知 捕获SIGWIN
  • 如何从 appsettings.json 文件中的对象数组读取值

    我的 appsettings json 文件 StudentBirthdays Anne 01 11 2000 Peter 29 07 2001 Jane 15 10 2001 John Not Mentioned 我有一个单独的配置类 p
  • python获取上传/下载速度

    我想在我的计算机上监控上传和下载速度 一个名为 conky 的程序已经在 conky conf 中执行了以下操作 Connection quality alignr wireless link qual perc wlan0 downspe
  • 如何设计以 char* 指针作为类成员变量的类?

    首先我想介绍一下我的情况 我写了一些类 将 char 指针作为私有类成员 而且这个项目有 GUI 所以当单击按钮时 某些函数可能会执行多次 这些类是设计的单班在项目中 但是其中的某些函数可以执行多次 然后我发现我的项目存在内存泄漏 所以我想
  • 如何在 C 中调用采用匿名结构的函数?

    如何在 C 中调用采用匿名结构的函数 比如这个函数 void func struct int x p printf i n p x 当提供原型的函数声明在范围内时 调用该函数的参数必须具有与原型中声明的类型兼容的类型 其中 兼容 具有标准定
  • 这些作业之间是否存在顺序点?

    以下代码中的两个赋值之间是否存在序列点 f f x 1 1 x 2 不 没有 在这种情况下 标准确实是含糊不清的 如果你想确认这一点 gcc 有这个非常酷的选项 Wsequence point在这种情况下 它会警告您该操作可能未定义
  • Windows 窗体:如果文本太长,请添加新行到标签

    我正在使用 C 有时 从网络服务返回的文本 我在标签中显示 太长 并且会在表单边缘被截断 如果标签不适合表单 是否有一种简单的方法可以在标签中添加换行符 Thanks 如果您将标签设置为autosize 它会随着您输入的任何文本自动增长 为
  • 覆盖子类中的字段或属性

    我有一个抽象基类 我想声明一个字段或属性 该字段或属性在从该父类继承的每个类中具有不同的值 我想在基类中定义它 以便我可以在基类方法中引用它 例如覆盖 ToString 来表示 此对象的类型为 property field 我有三种方法可以
  • WPF/C# 将自定义对象列表数据绑定到列表框?

    我在将自定义对象列表的数据绑定到ListBox in WPF 这是自定义对象 public class FileItem public string Name get set public string Path get set 这是列表
  • 向现有 TCP 和 UDP 代码添加 SSL 支持?

    这是我的问题 现在我有一个 Linux 服务器应用程序 使用 C gcc 编写 它与 Windows C 客户端应用程序 Visual Studio 9 Qt 4 5 进行通信 是什么very在不完全破坏现有协议的情况下向双方添加 SSL
  • cmake 将标头包含到每个源文件中

    其实我有一个简单的问题 但找不到答案 也许你可以给我指一个副本 所以 问题是 是否可以告诉 cmake 指示编译器在每个源文件的开头自动包含一些头文件 这样就不需要放置 include foo h 了 谢谢 CMake 没有针对此特定用例的
  • 如何在Xamarin中删除ViewTreeObserver?

    假设我需要获取并设置视图的高度 在 Android 中 众所周知 只有在绘制视图之后才能获取视图高度 如果您使用 Java 有很多答案 最著名的方法之一如下 取自这个答案 https stackoverflow com a 24035591
  • C# 成员变量继承

    我对 C 有点陌生 但我在编程方面有相当广泛的背景 我想做的事情 为游戏定义不同的 MapTiles 我已经像这样定义了 MapTile 基类 public class MapTile public Texture2D texture pu
  • 基于 OpenCV 边缘的物体检测 C++

    我有一个应用程序 我必须检测场景中某些项目的存在 这些项目可以旋转并稍微缩放 更大或更小 我尝试过使用关键点检测器 但它们不够快且不够准确 因此 我决定首先使用 Canny 或更快的边缘检测算法 检测模板和搜索区域中的边缘 然后匹配边缘以查
  • 在 MySQL 中存储表情符号的编码问题:如何使用 Prisma ORM 在 NodeJS 中定义字符排序规则?

    亲爱的 Nodejs 专家和数据库专家 我们在 MySQL 数据库中存储表情符号和其他特殊字符时遇到问题 我们使用 Prisma 得到一个错误 这是我们使用的 ORM 参数无法从排序规则 utf8 general ci 转换为 utf8mb
  • 哪种 C 数据类型可以表示 40 位二进制数?

    我需要表示一个40位的二进制数 应该使用哪种 C 数据类型来处理这个问题 如果您使用的是 C99 或 C11 兼容编译器 则使用int least64 t以获得最大的兼容性 或者 如果您想要无符号类型 uint least64 t 这些都定

随机推荐

  • C++类中this指针的理解

    https www cnblogs com liushui sky p 5802981 html 很好的文
  • 中国国家气象局天气预报信息接口

    想在自己的android应用中获得当天的天气情况 这该怎么做呢 不用担心 中国国家气象局提供了获取所在城市天气预报信息接口 通过这个接口 我们就可以获取天气信息了 中国国家气象局天气预报接口总共提供了三个 http www weather
  • 【人工智能业务概述】—人工智能的技术框架

    人工智能业务概述 人工智能的技术框架 人工智能的技术框架按照产业生态通常可以划分为基础层 技术层 应用层三大板块 其中 基础层提供了支撑人工智能应用的基础设施和技术 包括存储和处理大规模数据的能力 以及高性能的计算和通信基础设施 技术层提供
  • 怎么查看华为服务器型号,云服务器型号查看

    云服务器型号查看 内容精选 换一换 华为云帮助中心 为用户提供产品简介 价格说明 购买指南 用户指南 API参考 最佳实践 常见问题 视频帮助等技术文档 帮助您快速上手使用华为云服务 根据后端云服务器组的ID查询后端云服务器组详情 GET
  • FFmpeg编译与集成

    Java是 write once run anywhre 但 C 不一样 各平台均有差异 无法只写一次 而且各个平台的编译都不一样 比如android的ndk工具链 不同平台的库都是不一样的 本文主要讲解下 ffmpeg 在 win 平台下
  • 【Java基础篇】一文搞懂Java方法的调用与重载(超详细)

    个人主页 兜里有颗棉花糖 欢迎 点赞 收藏 留言 加关注 本文由 兜里有颗棉花糖 原创 收录于专栏 JavaSE primary 目录 一 方法的概念以及使用 1 1什么是方法 1 2方法定义 1 3方法调用的执行过程 1 4形参和实参的关
  • Python —— PyQT5 安装及配置

    PyQT5 安装及配置 下载离线安装包 测试 Pycharm配置qt designer扩展 配置 QTdesigner 配置PyUIC 配置PyRCC 测试扩展的可用性 如果报错 下载离线安装包 PyQT5 5 15 whl 文件大概60M
  • C# 9.0 新特性预览 - 类型推导的 new

    前言 随着 NET 5 发布日期的日益临近 其对应的 C 新版本已确定为 C 9 0 其中新增加的特性 或语法糖 也已基本锁定 本系列文章将向大家展示它们 目录 C 9 0 新特性预览 类型推导的 new C 9 0 新特性预览 空参数校验
  • python输出中文字符

    coding utf 8 import as import matplotlib pyplot as plt 解决中文显示问题 plt rcParams font sans serif SimHei plt rcParams axes un
  • C语言---离散数学实验--集合及二元关系的应用

    目录 集合的运算 题目要求 代码 等价关系的判定 题目要求 代码 N元关系 题目描述 代码 集合的运算 题目要求 一 集合的运算 1 用数组A B C E表示集合 输入数组A B E 全集 输入数据时要求检查数据是否重复 集合中的数据要求不
  • 网络安全和黑客技能:15本必读书籍推荐

    前言 网络安全和黑客技能紧密相连 想要有效地防范黑客攻击 了解黑客的技能和思维方式非常重要 而要想成为一名合格的白帽黑客 也需要深入理解网络安全的基本原理和最佳实践 本文将介绍15本网络安全和黑客书籍 既包括了防范黑客攻击的指南书籍 也包括
  • ubuntu配置VLAN的方法

    目录 前言 一 VLAN是什么 二 Ubuntu如何配置VLAN IP 1 依赖安装 2 创建VLAN 总结 前言 在做someip相关开发的时候需要使用到VLAN 这里介绍如何在ubuntu上创建VLAN 一 VLAN是什么 VLAN V
  • RFID技术的优势

    什么是RFID技术 RFID射频识别是一种非接触式的自动识别技术 它通过射频信号自动识别目标对象并获取相关数据 识别工作无须人工干预 可工作于各种恶劣环境 EFID技术可识别高速运动物体并可同时识别多个标签 操作快捷方便 短距离射频产品不怕
  • 性能测试总结

    性能调优是什么 我们为什么要进行性能调优 主要是由以下几个点来考虑 1 编写的新应用上线前在性能上无法满足需求 这个时候需要对系统进行性能调优 2 应用系统在线上运行后随着系统数据量的不断增长 访问量的不断上升 系统的响应速度通常越来越慢
  • object-fit和object-position实现图片原比例裁剪不拉伸适应

    img标签的图片设置width 100 height 211px 默认图片拉伸或压缩以适应此宽高 原有 但是这样太丑了 所以我们需要把图片裁剪一下 让它不拉伸以原有比例填充屏幕 首先使用到object fit这个属性 objtct fit
  • 【统计模拟及其R实现】逆变换 / 筛选法 / 合成法 上机习题答案(超详细)

    课本 统计模拟及其R实现 肖枝红 朱强 武汉大学出版社 参考课件 第三章 随机数 浙江大学数学科学学院 目录 1 逆变换法 2 筛选法 3 合成法 1 逆变换法 题目1 用逆变换方法生成如下密度函数的随机变量 要求写出R程序 Cauchy概
  • 基于python的端口扫描(升级版)

    今天给大家带来一个用python写的端口扫描小程序 需要借助一个python的库 Scapy是一个强大的Python库 用于构建和发送网络数据包 以及对网络进行各种类型的分析和操作 pip install scapy 通过Scapy 您可以
  • modbus详尽中文资料、软件、代码

    modbus详尽中文资料 软件 代码
  • linux bootarg 数组,Linux启动bootargs参数分析

    Linux启动bootargs参数分析 Written by leeming 这几天刚好在看linux c语言启动 现在就顺便把内核在启动时解析bootargs这一块单独拎出来讲解下 内核对于bootargs的解析分为几块 1 setup
  • linux下使用C语言操作MYSQL数据库(API使用libmysqlclient-dev)

    文章目录 运行环境 一 准备工作 1 在Ubuntu上准备mysql开发环境 2 创建测试数据库与表 二 建立与mysql的连接 1 在C文件中引入头文件 2 初始化mysql与数据库的通道 3 与mysql建立真实连接 三 添加操作 CR