C++封装对MySQL的基本操作

news2024/11/24 16:24:01

1.环境搭建

在这里,我将使用vscode来搭建MySQL的编程环境。

首先,下载MySQL,配置好系统环境变量并运行MySQL数据库。

接着,vscode扩展中搜索并下载MySQLMySQL Syntax插件。

安装完成后,在资源管理器的MySQL栏中点击+号,依次输入host名称、用户名、密码和端口号(最后一项可为空)来与数据库创建链接。

接下来,我们需要在c_cpp_properties.json的includePath中添加MySQL的include路径。

当我们通过命令行编译文件时,需要通过-L参数来指定MySQL的lib目录路径,通过-l参数来指定所要链接的库

g++ .\main.cpp -L "C:\Program Files\MySQL\MySQL Server 8.0\lib" -l libmysql -o main

当然,我们也可以在tasks.json的arg参数中进行相应的设置。

"args": [
	"-g",
	"${workspaceFolder}\\main.cpp",
	"-L",
	"C:\\Program Files\\MySQL\\MySQL Server 8.0\\lib",
	"-l",
	"libmysql",
	"-o",
	"${workspaceFolder}\\main.exe"
]

下面,我们就可以在我们的项目中包含mysql.h的头文件了。

然而,在实际操作的过程中,vscode居然会在运行阶段产生如下的错误:

Unable to start debugging. Unexpected GDB output from command “-exec-run”.

经过大量的尝试,我们只需要将lib目录中的.dll文件搬到项目目录下就可以正常运行了。

到这里,我们就完成了MySQL的环境搭建。


2.MySQL基本类型

2.1 数据定义语言(Data Definition Language)

主要用于对数据对象的创建,即在正式开发前对数据库及表的操作。

2.2 数据操作语言(Data Manipulation Language)

主要用于对数据的修改与查询,在开发过程中往往作为核心部分与其他编程语言进行交互。

2.3 数据控制语言(Data Control Language)

用于数据库的权限管理操作,一般由数据库的管理员来负责。


3.MySQL基本语句(部分)

3.1 数据库操作语句

显示所有数据库

SHOW DATABASES;

创建数据库

CREATE DATABASE 数据库名;

删除数据库

DROP DATABASE 数据库名;

使用数据库

use 数据库名;

显示当前数据库下的所有数据表

show tables;

3.2 表操作

创建表

CREATE TABLE 
    (IF NOT EXISTS) 表名(
        变量1 类型1 [约束],
        变量2 类型2 [约束],
        ...
        变量n 类型n [约束]
    );

查看表结构

DESCRIBE 表名;

删除表

DROP TABLE 表名;

3.3 数据操作

插入数据

INSERT INTO
    表名 (变量1,变量2,...,变量n) 
VALUES (值1,值2,...,值n);

删除数据

DELETE FROM 表名 WHERE [条件]

修改数据

UPDATE 表名
SET 变量1 = 值1, 变量2 = 值2, ..., 变量n = 值n
WHERE [条件]

查询数据

SELECT * FROM 表名 [WHERE 条件]

4.MySQL.h基本库函数

  • mysql_init : 初始化MYSQL对象

  • mysql_options : 对MYSQL对象进行特殊设置

  • mysql_real_connect : 将MYSQL对象连接到数据库

  • mysql_query : 执行mysql语句并查询执行结果(执行结果将被存储),若执行成功则返回零,否则返回非零

  • mysql_store_result : 获取上一次查询的执行结果,用MYSQL_RES对象接收

  • mysql_fetch_row : 获取执行结果中的一行数据(可视为数组)

  • mysql_free_result : 释放MYSQL_RES对象的空间

  • mysql_close : 关闭MYSQL对象


5.封装对数据库的增删改查操作

5.1 信息类的封装

为了方便模拟和测试,我们设计如下的信息类:

/*info.h*/
#ifndef INFO_H
#define INFO_H
#include <iostream>

class Info
{
    int id;
    std::string name;
    int price;
    std::string detail;

public:
    int get_id() const;
    std::string get_name() const;
    int get_price() const;
    std::string get_detail() const;

    Info(int, std::string, int, std::string);
};

#endif
/*info.cpp*/
#include"info.h"

int Info::get_id() const
{
    return id;
}

std::string Info::get_name() const
{
    return name;
}

int Info::get_price() const
{
    return price;
}

std::string Info::get_detail() const
{
    return detail;
}

Info::Info(int _id, std::string _name, int _price, std::string _detail)
    : id(_id), name(_name), price(_price), detail(_detail){}

5.2 数据访问对象的封装

对于DAO类,我们采用单例模式来进行封装来避免实例化多个对象。我们将DAO类的构造函数私有化,并创建一个静态DAO对象,通过调用特定的静态方法get_instance来获得对象,这样就实现了单例模式。

/*dao.h*/
#ifndef DAO_H
#define DAO_H
#include <winsock.h>
#include "C:\Program Files\MySQL\MySQL Server 8.0\include\mysql.h"
#include <iostream>
#include <vector>
#include "info.h"

class DAO
{
public:
    static DAO *get_instance();
    bool insert_info(Info &info);
    bool update_info(Info &info);
    bool delete_info(int &id);
    std::vector<Info> get_info(std::string condition) const;

private:
    const char *host = "127.0.0.1";// ip地址
    const char *user = "root";// 用户名
    const char *pw = "123456";// 密码
    const char *database_name = "sqldemo";// 数据库名
    const char *table_name = "information";// 所要查询的表名
    const int port = 3306;// 端口号

    MYSQL *con;
    static DAO *dao;

    bool connect();
    DAO();
    ~DAO();
};

#endif
/*dao.cpp*/
DAO *DAO::dao = new DAO();

DAO *DAO::get_instance()
{
    return dao;
}

5.3 实现对数据库的增删改

对于数据库的增删改,我们都可以直接通过mysql语句来实现,只要通过mysql_query判断语句是否执行成功即可。

/*dao.cpp*/
bool DAO::insert_info(Info &info)
{
    char sql[2048];
    sprintf(sql, "insert into %s (id,name,price,detail) values(%d,'%s',%d,'%s')", table_name, info.get_id(), info.get_name().c_str(), info.get_price(), info.get_detail().c_str());
    if (mysql_query(con, sql))
    {
        fprintf(stderr, "Failed to insert data : Error:%s\n", mysql_error(con));
        return false;
    }
    return true;
}

bool DAO::update_info(Info &info)
{
    char sql[2048];
    sprintf(sql, "update %s set name = '%s',price = %d,detail = '%s' where id = %d", table_name, info.get_name(), info.get_price(), info.get_detail(), info.get_id());
    if (mysql_query(con, sql))
    {
        fprintf(stderr, "Failed to update data : Error:%s\n", mysql_error(con));
        return false;
    }
    return true;
}

bool DAO::delete_info(int &id)
{
    char sql[2048];
    sprintf(sql, "delete from %s where id = %d", table_name, id);
    if (mysql_query(con, sql))
    {
        fprintf(stderr, "Failed to delete data : Error:%s\n", mysql_error(con));
        return false;
    }
    return true;
}

5.4 实现对数据库的查询

在这里,我们通过vector容器来返回所有查询到的对象,通过传入condition来补全mysql语句中的查询条件,从查询结果中逐行获取信息对象并存入容器中。

/*dao.cpp*/
std::vector<Info> DAO::get_info(std::string condition) const
{
    std::vector<Info> info_list;
    char sql[2048];
    sprintf(sql, "select * from %s%s", table_name, condition.c_str());
    if (mysql_query(con, sql))
    {
        fprintf(stderr, "Failed to select data : Error:%s\n", mysql_error(con));
        return {};
    }
    MYSQL_RES *res = mysql_store_result(con);
    MYSQL_ROW row;
    while ((row = mysql_fetch_row(res)))
    {
        Info info(atoi(row[0]), row[1], atoi(row[2]), row[3]);
        info_list.push_back(info);
    }
    mysql_free_result(res);
    return info_list;
}

6.完整代码

/*info.h*/
#ifndef INFO_H
#define INFO_H
#include <iostream>

class Info
{
    int id;
    std::string name;
    int price;
    std::string detail;

public:
    int get_id() const;
    std::string get_name() const;
    int get_price() const;
    std::string get_detail() const;

    Info(int, std::string, int, std::string);
};

#endif
/*info.cpp*/
#include"info.h"

int Info::get_id() const
{
    return id;
}

std::string Info::get_name() const
{
    return name;
}

int Info::get_price() const
{
    return price;
}

std::string Info::get_detail() const
{
    return detail;
}

Info::Info(int _id, std::string _name, int _price, std::string _detail)
    : id(_id), name(_name), price(_price), detail(_detail){}
/*dao.h*/
#ifndef DAO_H
#define DAO_H
#include <winsock.h>
#include "C:\Program Files\MySQL\MySQL Server 8.0\include\mysql.h"
#include <iostream>
#include <vector>
#include "info.h"

class DAO
{
public:
    static DAO *get_instance();
    bool insert_info(Info &info);
    bool update_info(Info &info);
    bool delete_info(int &id);
    std::vector<Info> get_info(std::string condition) const;

private:
    const char *host = "127.0.0.1";// ip地址
    const char *user = "root";// 用户名
    const char *pw = "123456";// 密码
    const char *database_name = "sqldemo";// 数据库名
    const char *table_name = "information";// 所要查询的表名
    const int port = 3306;// 端口号

    MYSQL *con;
    static DAO *dao;

    bool connect();
    DAO();
    ~DAO();
};

#endif
/*dao.cpp*/
#include "dao.h"

DAO *DAO::dao = new DAO();

DAO *DAO::get_instance()
{
    return dao;
}

bool DAO::connect()
{
    if (!mysql_real_connect(con, host, user, pw, database_name, port, NULL, 0))
    {
        fprintf(stderr, "Failed to connect to database : Error:%s\n", mysql_error(con));
        return false;
    }
    return true;
}

bool DAO::insert_info(Info &info)
{
    char sql[2048];
    sprintf(sql, "insert into %s (id,name,price,detail) values(%d,'%s',%d,'%s')", table_name, info.get_id(), info.get_name().c_str(), info.get_price(), info.get_detail().c_str());
    if (mysql_query(con, sql))
    {
        fprintf(stderr, "Failed to insert data : Error:%s\n", mysql_error(con));
        return false;
    }
    return true;
}

bool DAO::update_info(Info &info)
{
    char sql[2048];
    sprintf(sql, "update %s set name = '%s',price = %d,detail = '%s' where id = %d", table_name, info.get_name(), info.get_price(), info.get_detail(), info.get_id());
    if (mysql_query(con, sql))
    {
        fprintf(stderr, "Failed to update data : Error:%s\n", mysql_error(con));
        return false;
    }
    return true;
}

bool DAO::delete_info(int &id)
{
    char sql[2048];
    sprintf(sql, "delete from %s where id = %d", table_name, id);
    if (mysql_query(con, sql))
    {
        fprintf(stderr, "Failed to delete data : Error:%s\n", mysql_error(con));
        return false;
    }
    return true;
}

std::vector<Info> DAO::get_info(std::string condition) const
{
    std::vector<Info> info_list;
    char sql[2048];
    sprintf(sql, "select * from %s%s", table_name, condition.c_str());
    if (mysql_query(con, sql))
    {
        fprintf(stderr, "Failed to select data : Error:%s\n", mysql_error(con));
        return {};
    }
    MYSQL_RES *res = mysql_store_result(con);
    MYSQL_ROW row;
    while ((row = mysql_fetch_row(res)))
    {
        Info info(atoi(row[0]), row[1], atoi(row[2]), row[3]);
        info_list.push_back(info);
    }
    mysql_free_result(res);
    return info_list;
}

DAO::DAO()
{
    con = mysql_init(NULL);
    mysql_options(con, MYSQL_SET_CHARSET_NAME, "GBK");
    connect();
}

DAO::~DAO()
{
    mysql_close(con);
}

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

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

相关文章

从0到1完成一个Node后端(express)项目(五、session、token)

往期 从0到1完成一个Node后端&#xff08;express&#xff09;项目&#xff08;一、初始化项目、安装nodemon&#xff09; 从0到1完成一个Node后端&#xff08;express&#xff09;项目&#xff08;二、下载数据库、navicat、express连接数据库&#xff09; 从0到1完成一个Nod…

“暗黑天使”降临:DarkAngels勒索病毒全解密

恶意文件分析 恶意文件描述 近期&#xff0c;深信服深盾终端实验室在运营工作中发现了一种 ELF 格式的勒索软件&#xff0c;该勒索软件近期开始出现&#xff0c;其释放的勒索信中的 Onion 链接似乎已关闭&#xff0c;这表明该勒索软件可能仍在开发中。 经过分析&#xff0c;…

AtCoder Beginner Contest 281 (A-F,口胡G)青大acmer 日常vp

A - Count Down 输出小于等于nnn的数 代码 B - Sandwich Number 题意 问字符串是否是第一个和最后一个字符是大小写&#xff0c;中间的字符是100000−99999100000-99999100000−99999之间的数字。 暴力模拟即可&#xff0c;需要注意的例子是A0100000AA0100000AA0100000A 代码 …

day14-常用API

1.API 1.1 API概述【理解】 什么是API ​ API (Application Programming Interface) &#xff1a;应用程序编程接口 java中的API ​ 指的就是 JDK 中提供的各种功能的 Java类&#xff0c;这些类将底层的实现封装了起来&#xff0c;我们不需要关心这些类是如何实现的&#xff…

VScode-git提交 无法推送refs到远端

在将代码同步到远端仓库时&#xff0c;弹窗提醒”无法推送refs到远端。您可以试着运行”拉取”功能&#xff0c;整合您的更改“ 但尝试后发现“拉取”功能也无法解决问题&#xff0c;最后是因为文件过大原因&#xff0c;在这里记录一下解决方法&#xff0c;并整理了另一种可能…

传输层协议:套接字Socket

介绍 socket是一种操作系统提供的进程间通信机制。 在操作系统中&#xff0c;通常会为应用程序提供一组应用程序接口&#xff08;API&#xff09;&#xff0c;称为套接字接口&#xff08;英语&#xff1a;socket API&#xff09;。应用程序可以通过套接字接口&#xff0c;来使…

大数据分析案例-基于决策树算法构建金融反欺诈分类模型

&#x1f935;‍♂️ 个人主页&#xff1a;艾派森的个人主页 ✍&#x1f3fb;作者简介&#xff1a;Python学习者 &#x1f40b; 希望大家多多支持&#xff0c;我们一起进步&#xff01;&#x1f604; 如果文章对你有帮助的话&#xff0c; 欢迎评论 &#x1f4ac;点赞&#x1f4…

春节期间外贸老鸟们都会掌握的那些事(内含祝福话术及邮件模板)

中国外贸规模在长期疫情的大环境下&#xff0c;外贸业界克服诸多困难&#xff0c;实现了量稳质升。随着我们迈入2023年&#xff0c;外贸人除了需要继续“强身健体”外&#xff0c;同时也将面临更多的挑战&#xff0c;本期Boom将从四个维度给大家分享临近中国春节期间&#xff0…

入门PostgreSQL,pg的历史,为什么说pg是国产化的方向,与mysql的比较

目录一、PG简介1、PG的历史2、PG的社区3、PostgreSQL与MySQL的比较一、PG简介 PostgreSQL 是一个免费的对象-关系数据库服务器(ORDBMS)&#xff0c;在灵活的BSD许可证下发行。 PostgreSQL 开发者把它念作 post-gress-Q-L。 PostgreSQL 的 Slogan 是 “世界上最先进的开源关系…

python-MySQL数据库基础(三)MySQL与python交互

MySQL与python交互 用python代码来连接数据库&#xff0c;执行SQL语句&#xff0c;来查询到数据库中的数据。 当一张表中的数据量比较多时&#xff0c;而我们只需要查询其中的某个字段数据&#xff0c;直接查询会导致效率降低&#xff0c;此时就需要建立分表。 python操作MySQ…

君乐宝,高端之路不好走

文|螳螂观察 作者|kinki 近日&#xff0c;奶粉巨头雅培发表声明称&#xff0c;将逐步停止中国大陆市场的婴幼儿和儿童营养产品的运营和销售&#xff0c;一直以来&#xff0c;雅培都是中国奶粉市场前十名的“常客”&#xff0c;但近年却跌出了“前十”的位置。 雅培的退出&am…

2023年DataWhale 1月Free Excel 第三次打卡

第三章 Excel的表合并 Excel的合并计算工具可以快速完成多个表的行列记录合并。 1.多表行合并 问题&#xff1a;在3个消费表格中&#xff0c;每个客户的消费金额不同&#xff0c;使用多表合并功能统计每个客户消费的总金额。 具体步骤&#xff1a; 1.选择需要汇总的单元格…

ZooKeeper 技术内幕|Leader 选举是一个什么样的过程

几个问题&#xff0c;引发思考&#xff1a; 什么时候 leader 选举&#xff1f; 选举的过程&#xff1f; 选举过程中&#xff0c;是否能提供服务&#xff1f; 选举结果&#xff0c;是否会丢失数据&#xff1f; 服务器角色 2 个小问题&#xff1a; 服务器节点有多少角色&…

如何实现连杆码垛机械臂的逆解计算?

1. 连杆码垛机械臂介绍 连杆码垛机器人是工业应用场景中常用的一种机械臂&#xff0c;常用于简单的大负载搬运作业场景。常见的连杆码垛机械臂都是4个自由度&#xff0c;相较于6轴和7轴的机械臂成本较低。 连杆码垛机械臂的运动特性是&#xff1a;末端始终平行于地面。第一个平…

【算法】一篇文章弄清楚KMP算法的实现

目录 前言&#xff1a; 一.KMP算法简介&#xff1a; 二.next数组的介绍及实现 三.next数组的优化 四.伪代码和完整代码的实现 总结&#xff1a; 博客主页&#xff1a;张栩睿的博客主页 欢迎关注&#xff1a;点赞收藏留言 系列专栏&#xff1a;c语言学习 家人们写博客真…

小白的性能测试探索之路(1)

​​​​​​​ 某一天&#xff0c;领导突然就拉了个会说&#xff0c;我们成立稳定性专项&#xff0c;以测试为主力提升服务的整体稳定性&#xff1f; 当时我的内心是&#xff1a;“what”&#xff0c;性能测试我完全没接触过呀&#xff0c;i am a little tester&#xff5e;而…

华为MPLS-HubSub组网实验配置

目录 配置接口IP地址以及底层IGP协议 配置MPLS LDP协议 Sub与Hub建立Vpnv4邻居 配置PE与CE对接命令 Sub-PE与CE对接配置 Hub与CE对接配置 发现问题 PE与CE之间都采用EBGP方式进行路由传递 MPLS隧道——Hub&Spoke组网_静下心来敲木鱼的博客-CSDN博客_hub spokehttps…

Flume第二章:企业案例

系列文章目录 Flume第一章&#xff1a;环境安装 Flume第二章&#xff1a;企业案例 文章目录系列文章目录前言一、复制和多路复用1.案例需求2.案例实现3.结果查看二、负载均衡和故障转移1.需求案例2.案例实现3.结果查看三、聚合1.案例需求2.案例实现3.查看结果总结前言 这次我…

用python写的代码输入助手小程序(附源码)

命令太多&#xff0c;很容易忘记&#xff0c;还有很多代码片段想保存下来用到的时候能够快速输入&#xff0c;提高开发效率。在网上找了很多&#xff0c;发现都不是自己想要的。于是就用python写了一个自己用的代码输入助手小程序&#xff0c;我自己已经用了很长时间了&#xf…

工业中常用流量计及其测量原理

一、流量计单位 工程上常用单位m3/h&#xff0c;它可分为瞬时流量&#xff08;Flow Rate&#xff09;和累计流量&#xff08;Total Flow&#xff09;&#xff0c;瞬时流量即单位时间内过封闭管道或明渠有效截面的量&#xff0c;流过的物质可以是气体、液体、固体&#xff1b;累…