Linux安装MySQL数据库并使用C语言进行数据库开发

目录

一、前言

二、安装VMware运行Ubuntu

1.安装VMware

2.使用VMware打开Ubuntu

三、配置VMware使用网卡

1.添加NAT网卡

四、Linux下安装MySQL数据库

五、安装MySQL开发库

六、演示代码

sql_connect.c

sql_connect.h

main.c中数据库相关代码

结尾


一、前言

由于最近在做项目,需要用到数据库,想在Linux服务端使用C语言操作MySQL数据库,于是写一篇博客记录一下。希望大伙点个关注支持一下,不久后就更新项目博客。


二、安装VMware运行Ubuntu

1.安装VMware

Windows 下有很多虚拟机软件,目前市面上流行的有VMware和VirtualBox。VMware 分为收费专业版 Workstation Pro 和非商用免费版 Workstation Player,推荐使用Workstation Player

我使用的是韦东山老师提供的 Ubuntu 镜像文件,链接:Linux虚拟机环境 。VMWare 安装软件是:VMware-workstation-full-16.2.3-19376536.exe。下面给出VMWare的安装步骤。

第1步:以管理员身份运行安装软件:

第2步:点击"下一步":

第3步:勾选"我接受"点击"下一步":

第4步:指定安装目录后点击"下一步":

第5步:设置用户体验后点击"下一步":

第6步:设置快捷方式后点击"下一步":

第7步:点击"安装"开始安装:

第8步:等待安装完成:

第9步:完成安装:

VMWare 安装完成后,有两个软件,它们都可以使用,建议使用第2个:

① Vmware Workstation Pro:这是收费的,可以试用30天。

② Vmware Workstation 16 Player:这是免费的。

2.使用VMware打开Ubuntu

解压Ubuntu镜像压缩包后,可以得到如图所示文件:

注意:在打开之前,请先确保您的电脑的BIOS已经启动了虚拟化,可以打开设备管理器确认这点,如图所示:

然后查看是否启动了虚拟化:

确认打开后,就可以使用VMware打开Ubuntu镜像了:

第1步:以管理员身份打开Vmware Workstation 16 player:

第2步:打开虚拟机,使用vmware打开前面解压得到的"Ubuntu 18.04_x64.vmx":

第3步:播放虚拟机:

第4步:第一次启动Ubuntu时,选择默认的"我已复制该虚拟机",启动后输入密码"123456"回车即可登录:

注意:虚拟机默认没有开启小键盘,如果使用小键盘输入,请先开启小键盘


三、配置VMware使用网卡

1.添加NAT网卡

使用韦东山老师团队制作的Ubuntu映像时,它已经添加了NAT网卡,无需再添加NAT网卡。如果你的Ubuntu虚拟机中没有NAT网卡,则可以如图所示添加NAT网卡:

① 点击进入"编辑虚拟机设置";

② 如果没有NAT模式的网卡,则继续下一步;

③ 点击"添加";

④ 选择"网络适配器";

⑤ 点击"完成";

⑥ 设置新添加的"网络适配器"的"网络连接"为"NAT模式";

⑦ 点击确定完成NAT网卡的添加;

添加NAT网卡后,可以启动Ubuntu,使用 ifconfig 命令查看IP,再使用 ping 命令确认可以连接外网:

至此前期的准备工作就结束了!下面准备安装MySQL数据库。


四、Linux下安装MySQL数据库

直接在终端按顺序输入以下命令即可:

sudo apt install mysql-server

输入这个之后会让我们输入密码,也是123456。然后会问我们是否确定安装,输入Y即可。

安装完之后会自动启动MySQL服务,使用下面的命令来查看服务状态:

systemctl status mysql

看到显示 active 就表示服务已经启动成功了:

如果没有启动的可以执行下面命令来启动:

systemctl start mysql

然后输入密码即可。

接着我们来修改一下密码,这个密码是进入MySQL数据库的密码,不是Ubuntu的登陆密码,不要搞混了,以后我们使用MySQL开发库,通过C语言来操作数据库,肯定需要传入密码和IP等参数,我们现在就来修改这个密码。

Linux系统安装完之后默认是有密码的,如果输入的密码错误,当然也就无法连接到MySQL的服务,输入以下命令可以找到默认的密码:

sudo cat /etc/mysql/debian.cnf

通过这个命令可以找到这个位置上的配置文件,它里面就记载了一个默认的用户名和密码,那我们就可以使用这个用户名和密码来连接MySQL的服务,输入命令如下:

mysql -u debian-sys-maint -p m6mhClGDw71Ko2yS

-u 后面是你的用户名,-p后面是密码,回车后就能连接到MySQL服务了。但是这个用户名和密码都不太好记,现在我们来修改密码和用户名,我们输入了上面那行命令后,已经连接到了MySQL服务,然后输入下面的语句修改:

alter user 'root'@'%' identified with mysql_native_password by '123456';

如果出错的话就把%改成localhost,修改成功后执行下面的语句刷新权限:

flush privileges;

之后就可以输入mysql -u root -p ,然后输入密码 123456 连接MySQL服务了,退出MySQL服务到终端的语句为exit;


五、安装MySQL开发库

我们要安装 libmysqlclient-dev 开发库,这个lib库是Linux下使用C/C++连接MySQL的客户端,安装步骤如下:

更新软件源:

sudo apt update

然后直接下载:

sudo apt install libmysqlclient-dev

这样我们就可以编写C语言来操作数据库了,详细内容可以看这个博主的博客,还是十分详细的:Linux(程序设计):18---libmysqlclient-dev库(C语言操作MySQL)-CSDN博客

注意:编译的时候需要指定头文件路径以及链接mysqlclient库,如下:

gcc demo.c -o demo -I/usr/include/mysql -lmysqlclient


六、演示代码

由于我对数据库也不是很了解,只学了点皮毛,项目中只用到了数据的插入、修改、删除和查询(如果你也是想用C语言对数据库进行简单操作,你可以参考我的代码),下面直接给出我用的代码给大家参考,我会说明功能和用法:

sql_connect.c

cpp 复制代码
#include "sql_connect.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// 初始化数据库连接对象
SQLifconfig* SQLifconfig_init() {
    SQLifconfig *config = (SQLifconfig*)malloc(sizeof(SQLifconfig));
    if (!config) return NULL;

    // 初始化成员变量
    config->mysql = NULL;
    config->row = NULL;
    config->result = NULL;

    // 初始化 MySQL 连接
    config->mysql = mysql_init(NULL);
    if (!config->mysql) {
        printf("Init Error: %s\n", mysql_error(config->mysql));
        free(config);
        return NULL;
    }

	// 强制设置字符集
    if (mysql_options(config->mysql, MYSQL_SET_CHARSET_NAME, "utf8mb4")) {
        printf("Set UTF-8 Error: %s\n", mysql_error(config->mysql));
        mysql_close(config->mysql);
        free(config);
        return NULL;
    }

    return config;
}

// 释放数据库连接对象
void SQLifconfig_destroy(SQLifconfig *config) {
    if (config) {
        if (config->mysql) {
            mysql_close(config->mysql);
        }
        free(config);
    }
}

// 初始化数据库连接
bool SQLifconfig_SQL_init(SQLifconfig *config, const char *host, const char *user, const char *pwd, const char *dbname) {
    if (!mysql_real_connect(config->mysql, host, user, pwd, dbname, 3306, NULL, 0)) {
        printf("connect error: %s\n", mysql_error(config->mysql));
        return false;
    }
    return true;
}

// 执行操作 SQL 语句(INSERT/UPDATE/DELETE)
bool SQLifconfig_Dml_sql(SQLifconfig *config, const char *sqlstr) {
    printf("sql: %s\n", sqlstr);

    // 开始事务
    if (mysql_query(config->mysql, "BEGIN")) {
        printf("query_error: %s\n", mysql_error(config->mysql));
        return false;
    }

    // 执行 SQL 语句
    if (mysql_query(config->mysql, sqlstr)) {
        printf("query_error: %s\n", mysql_error(config->mysql));
        return false;
    }

    // 提交事务
    if (mysql_query(config->mysql, "COMMIT")) {
        printf("query_error: %s\n", mysql_error(config->mysql));
        return false;
    }

    return true;
}

// 执行查询 SQL 语句(SELECT)
char* SQLifconfig_Dql_sql(SQLifconfig *config, const char *sqlstr) {
    // 执行 SQL 查询
    if (mysql_query(config->mysql, sqlstr)) {
        printf("query_error: %s\n", mysql_error(config->mysql));
        return NULL;
    }

    // 获取查询结果集
    config->result = mysql_store_result(config->mysql);
    if (!config->result) {
        return NULL; // 无结果或错误
    }

    // 获取字段数量
    int fieldnum = mysql_num_fields(config->result);

    // 初始化动态缓冲区
    size_t total_len = 1024; // 初始缓冲区大小
    char *buffer = (char*)malloc(total_len);
    if (!buffer) {
        mysql_free_result(config->result);
        return NULL; // 内存分配失败
    }
    buffer[0] = '\0'; // 初始化空字符串

    // 遍历结果集的每一行
    while ((config->row = mysql_fetch_row(config->result))) {
        // 计算当前行所需的总长度
        size_t row_len = 0;
        for (int j = 0; j < fieldnum; j++) {
            row_len += strlen(config->row[j] ? config->row[j] : "NULL") + 1; // 字段值 + 分隔符
        }

        // 动态扩展缓冲区(如果当前缓冲区不足以容纳新行)
        size_t current_len = strlen(buffer);
        if (current_len + row_len + 2 > total_len) {
            total_len += row_len + 2; // 扩展缓冲区大小
            char *new_buf = realloc(buffer, total_len);
            if (!new_buf) {
                free(buffer);
                mysql_free_result(config->result);
                return NULL; // 内存分配失败
            }
            buffer = new_buf;
        }

        // 拼接当前行的字段值
        for (int j = 0; j < fieldnum; j++) {
            const char *val = config->row[j] ? config->row[j] : "NULL"; // 处理 NULL 值
            strcat(buffer, val); // 追加字段值
            strcat(buffer, "#"); // 追加分隔符
        }
        buffer[strlen(buffer)-1] = '\n'; // 将最后一个#替换为换行符
    }

    // 释放结果集内存
    mysql_free_result(config->result);

    // 检查是否有有效数据
    if (strlen(buffer) == 0) {
        free(buffer);
        return NULL; // 无数据
    }

    // 返回格式化后的字符串
    return buffer;
}

sql_connect.h

cpp 复制代码
#ifndef __SQL_CONNECT_H
#define __SQL_CONNECT_H

#include <mysql.h>
#include <stdbool.h>

// 数据库连接结构体
typedef struct {
    MYSQL *mysql;       // MySQL 连接对象
    MYSQL_ROW row;      // 当前行数据
    MYSQL_RES *result;  // 查询结果集
} SQLifconfig;

// 初始化数据库连接
SQLifconfig* SQLifconfig_init();

// 释放数据库连接
void SQLifconfig_destroy(SQLifconfig *config);

// 初始化数据库连接
bool SQLifconfig_SQL_init(SQLifconfig *config, const char *host, const char *user, const char *pwd, const char *dbname);

// 执行查询 SQL 语句(SELECT)
char* SQLifconfig_Dql_sql(SQLifconfig *config, const char *sqlstr);

// 执行操作 SQL 语句(INSERT/UPDATE/DELETE)
bool SQLifconfig_Dml_sql(SQLifconfig *config, const char *sqlstr);

#endif

main.c中数据库相关代码

cpp 复制代码
/*--------------------------*/
/*数据库初始化相关操作*/
// 初始化数据库连接对象
SQLifconfig *MySQL_Handler = SQLifconfig_init();
if (!MySQL_Handler) 
{
    printf("初始化数据库失败\n");
    return -1;
}
// 连接数据库
if (!SQLifconfig_SQL_init(MySQL_Handler, "127.0.0.1", "root", "123456", "testdatabase")) 
{
    printf("连接数据库失败\n");
    SQLifconfig_destroy(MySQL_Handler);
    return -1;
}
/*--------------------------*/

/*--------------------------*/
/*查询数据示例操作*/
char buf[100];
// 构造 SQL 查询语句
sprintf(buf, "select * from table where id='%s'", str);

char *result = SQLifconfig_Dql_sql(MySQL_handler, buf);
if(result)
{
    printf("查询到的数据:%s\n", buf);
    free(result); // 必须手动释放内存
}
//失败的话会返回NULL,同时在函数内部已经释放了内存,因此失败的分支不需要我们手动释放了
else
{
    write(customer->client_socket, "4\n", 2);
}
/*--------------------------*/

/*--------------------------*/
/*修改数据示例操作*/
char buf[100] = {0};
// 构造 SQL 删除语句,删除table表中id为AABBCCDD的一行数据
sprintf(buf, "DELETE FROM table WHERE id='%s'", "AABBCCDD");

// 执行 SQL 删除操作
int result = SQLifconfig_Dml_sql(MySQL_handler, buf);
if(result)
{
    //成功
}
else
{
    //失败
}
/*--------------------------*/

其实就是自己构造MySQL语句,可以去看看一些常用的语句,还是比较简单的,Dql函数会返回查询到的数据,每个字段都会用 # 分隔,每一行的数据最后还会加上 \n 换行符,比如说我要查询table中的所有数据,返回值如下:

id#name#level

id2#name2#level2

注意这里的每一行的末尾都会有换行符'\n',其中需要注意的是,如果你想查询表里的某一行数据的某个字段,如果这个位置你还没有写过数据,读出来的值是"NULL\n"字符串,并不是NULL,只有查询失败才会返回 NULL,可以仔细看一下我的代码。


结尾

分享到此结束了,后面我会更新Linux下C语言编写的服务端+Qt管理员端+Qt用户端+STM32用户端实现的无人超市项目,也是成功复刻了一个大佬的项目,学到了很多东西,希望大家点个关注支持一下。

相关推荐
nlog3n5 分钟前
MySQL 常见面试问题总结
java·数据库·mysql·面试
屎派克12 分钟前
linux和windows是采用何种机制保存密码的?
linux·运维·服务器
字节跳动开源19 分钟前
MySQL遇到AI:字节跳动开源 MySQL 虚拟索引 VIDEX
人工智能·mysql·开源·虚拟索引技术·解耦架构
碧海饮冰20 分钟前
MongoDB 与 Elasticsearch 使用场景区别及示例
数据库·mongodb·elasticsearch
张小九9921 分钟前
Linux修改默认shell为zsh
linux·运维·服务器
V---scwantop---信30 分钟前
复古卡通纹理噪点印刷打印照片效果PS特效样机 Texturizer Original Design Effect
笔记
搬码红绿灯35 分钟前
数据库——MySQL字符、日期函数
数据库·mysql
Tyler先森36 分钟前
Oracle数据库数据编程SQL<2.2 DDL 视图、序列>
数据库·sql·oracle
竹之却40 分钟前
【云服务器】在 Linux(Ubuntu / CentOS 7)上快速搭建我的世界 Minecraft 服务器,并实现远程联机,详细教程
linux·服务器·ubuntu·腾讯云·我的世界服务器搭建
郭涤生44 分钟前
第二章:影响优化的计算机行为_《C++性能优化指南》notes
开发语言·c++·笔记·性能优化