项目场景:
C++的课程设计,要用到mysql,花了点时间去查找资料把mysql的操作做了简单的封装。可以直接继承复用。
解决方案:
mysql_operate.h
#pragma once
#ifndef _MYSQL_OPERATE_H_
#define _MYSQL_OPERATE_H_
#include<iostream>
using namespace std;
#include<string>
#include<Windows.h>
#include<WinSock.h>
#include<mysql.h>
extern const int MAX_SQL_SENTENCE_LENGTH;
class Mysql_Operate
{
public:
Mysql_Operate();
~Mysql_Operate();
//连接数据库 参数为ip 用户名 密码 数据库名 端口
bool connect(const char* HOST, const char* USER, const char* PASSWORD, const char* DATABASE_NAME, const int PORT);
// 封装后的操作函数
template<class ... Args>
void excute_sql(const char* format, Args ... args); // 可直接执行sql语句
template<class ... Args>
float get_one_request_of_float(const char* format, Args ... args); // 从数据库获取单个数据(int)
template<class ... Args>
char* get_one_request_of_str(const char* format, Args ... args); // 从数据库获取单个数据(str)
template<class ... Args>
MYSQL_ROW get_row_request_of_str(const char* format, Args ... args); // 从数据库获取整行数据(str)
bool display__res(); // 打印结果集
bool query_table(const char* table_name); //查询并打印表 参数为表名 这个函数不能使用别名 便捷的打印表的数据(可用来测试) 直接输入表的名称
// 初步封装的函数
int get__res_field_num(); //获取结果集的字段数
int get__res_row_num(); // 返回结果集合中的行的数量 查询集为空返回0
MYSQL_RES* query(); // 执行查询语句 返回查询集 底层操作函数(不直接调用)
int get_tag_id(const char*); // 获取表的最后一行的id+1 (新行的id)
protected:
bool _state; //连接状态 true为已连接
MYSQL* _mysql; //mysql连接
MYSQL_RES* _res; //这个结构代表返回行的一个查询结果集
MYSQL_ROW _column; //一个行数据的类型安全(type-safe)的表示,表示数据行的列
char* _query; //查询语句 有的查询语句过长会导致内存不够 分配大一点
int excute_status; // sql语句执行状态 成功、失败
int _res_rows_num; // 结果集合中的行的数量 为0说明结果集为空
int field_num; // 结果集中字段数
string exit_params; // 退出操作参数
};
char* get_datetime(); // 返回字符串日期时间 往数据库录入当前时间
// 封装的执行sql语句 执行成功返回1 失败返回0
/*
使用方法:
excute_sql("UPDATE app_produce_data SET is_delete = 1 WHERE id = %d", produce_id)直接输入sql语句
*/
template<class ... Args>
void Mysql_Operate::excute_sql(const char* format, Args ... args) {
excute_status = 0; // 初始化状态参数
_res_rows_num = 0; // 初始化结果集数据行数
field_num = 0;
sprintf_s(_query, MAX_SQL_SENTENCE_LENGTH, format, args...);
if (query()) {
excute_status = 1; // sql语句执行成功 excute_status = 1
_res_rows_num = get__res_row_num(); // 结果集数据行数
field_num = get__res_field_num();
}
else {
excute_status = 0;
_res_rows_num = 0;
field_num = 0;
}
}
/*
使用方法:
get_one_request_of_int("SELECT produce_price FROM app_produce_data WHERE id='%d'", produce_id)直接输入sql语句
*/
// 从数据库获取单个数据(int)
template<class ... Args>
float Mysql_Operate::get_one_request_of_float(const char* format, Args ... args) {
excute_sql(format, args...);
_column = mysql_fetch_row(_res); // 获取第一行
//cout << atoi(_column[0]);
return atof(_column[0]); // 返回值
}
/*
使用方法:
get_one_request_of_str("SELECT produce_name FROM app_produce_data WHERE id = %d", produce_id), produce_id)直接输入sql语句
*/
// 从数据库获取单个数据(str)
template<class ... Args>
char* Mysql_Operate::get_one_request_of_str(const char* format, Args ... args) {
excute_sql(format, args...);
_column = mysql_fetch_row(_res); // 获取第一行
//cout << _column[0];
return _column[0]; // 返回值
}
// 从数据库获取整行数据(str)
template<class ... Args>
MYSQL_ROW Mysql_Operate::get_row_request_of_str(const char* format, Args ... args) {
excute_sql(format, args...);
_column = mysql_fetch_row(_res); // 获取第一行
//cout << _column[0];
return _column; // 返回值
}
#endif // _MYSQL_OPERATE_H_
mysql_operate.cpp
# include "mysql_operate.h"
# include <sstream>
# include <atltime.h>
const int MAX_SQL_SENTENCE_LENGTH = 1000;
// 数据库操作封装
/*
1.void excute_sql(const char* format, Args ... args)
1.获取sql语句执行状态 接收字符串执行sql语句 sql语句执行成功excute_status = 1 失败excute_status = 0
2.获取结果集数据行数 _res_rows_num
2.bool display__res(int field_num) 1.打印查询集
*/
// 构造函数
Mysql_Operate::Mysql_Operate()
{
_state = false; // 连接状态
_mysql = new MYSQL;
_query = new char[MAX_SQL_SENTENCE_LENGTH]; // 分配内存
_res = nullptr; // 初始化结果集
_column = nullptr; // 初始化结果行
memset(_query, NULL, sizeof(_query)); // 初始化查询语句
connect("localhost", "root", "898678", "supermarket_data", 3306); //连接数据库 参数为ip、用户名、密码、数据库名、端口
_res_rows_num = 0; // 结果集合中的行的数量 为0说明结果集为空
field_num = 0; // 结果集中字段数
exit_params = "0"; // 退出操作参数
}
// 析构函数
Mysql_Operate::~Mysql_Operate()
{
}
// 连接数据库
bool Mysql_Operate::connect(const char* HOST, const char* USER, const char* PASSWORD, const char* DATABASE_NAME, const int PORT)
{
if (_state == true)
{
cout << "Connected succeed" << endl;
return true;
}
//初始化mysql
mysql_init(_mysql);
//返回false则连接失败,返回true则连接成功
if (!(mysql_real_connect(_mysql, HOST, USER, PASSWORD, DATABASE_NAME, PORT, NULL, 0))) // 主机用户名、密码、数据库名、端口号
{
printf("Error connecting to database:%s\n", mysql_error(_mysql));
return false;
}
else
{
_state = true;
return true;
}
}
// 封装查询语句 返回结果集 执行失败返回nullptr
MYSQL_RES* Mysql_Operate::query() {
if (_state == false) // 判断数据库是否连接
{
printf("Database not connected\n");
return false;
}
//设置编码格式(SET NAMES GBK也行),否则cmd下中文乱码
mysql_query(_mysql, "set names gbk");
MYSQL_RES* error = nullptr;
// 获取查询结果 并进行查询结果判断
if (mysql_query(_mysql, _query)) //执行SQL语句
{
printf("Query failed (%s)\n", mysql_error(_mysql));
return error;
}
else
{
//printf("query success\n");
}
//获取结果集
if (!(_res = mysql_store_result(_mysql))) //获得sql语句结束后返回的结果集
{
//printf("Couldn't get result from %s\n", mysql_error(_mysql));
//return error;
}
if (_res == nullptr) {
_res = new MYSQL_RES; // 区分 插入、更新数据时无返回结果集导致无法sql语句判断是否执行成功 不让_res == error
}
return _res;
}
// 打印结果集
bool Mysql_Operate::display__res() {
char* str_field[MAX_SQL_SENTENCE_LENGTH]; // 字段名
for (int i = 0; i < field_num; i++) //在获得字段数量的情况下获取字段名
{
str_field[i] = mysql_fetch_field(_res)->name; // 返回下一个表字段名
}
//打印字段名 打印表的第一行字段名
for (int i = 0; i < field_num; i++)
{
printf("%10s\t", str_field[i]);
}
printf("\n");
//打印获取的数据
while (_column = mysql_fetch_row(_res)) //在已知字段数量情况下,获取并打印下一行 无下一行后mysql_fetch_row返回false结束循环
{
for (int i = 0; i < field_num; i++)
{
printf("%10s\t", _column[i]); //column是列数组 一行包括多列
}
printf("\n");
}
return true;
}
// 返回结果集合中的行的数量 查询集为空返回0
int Mysql_Operate::get__res_row_num() {
return mysql_num_rows(_res);
}
// 返回结果集中的字段数
int Mysql_Operate::get__res_field_num() {
return mysql_field_count(_mysql);
}
// 查询表 直接传入表名
bool Mysql_Operate::query_table(const char* table_name)
{
//查询内容
if (!strcmp(table_name, "app_produce_data")) { // 如果为商品信息表 增加是否删除判断
excute_sql("select * from %s WHERE is_delete = 0", table_name); //执行查询语句
}
else {
excute_sql("select * from %s", table_name); //执行查询语句
}
//打印数据行数
printf("number of dataline returned: %lld\n", mysql_affected_rows(_mysql));
// 打印表数据
display__res();
return true;
}
// 获取表的最后一行的id 在此基础上加1 返回新的一行的id
int Mysql_Operate::get_tag_id(const char* c) {
//查询内容
excute_sql("SELECT id FROM %s ORDER BY id DESC LIMIT 1", c);
_column = mysql_fetch_row(_res);
//printf("%10s\t", _column[0]); //column是列数组
if (_column == nullptr) {
return 1;
}
int row_num = atoi(_column[0]);
return row_num + 1;
}
//int to string
string inttostring(int in)
{
stringstream ss;
string str;
ss << in;
ss >> str;
return str;
}
// 返回字符串日期时间
char* get_datetime() {
//get the current time
CTime t = CTime::GetCurrentTime();
string mytime = inttostring(t.GetYear()) + "-" + inttostring(t.GetMonth()) + "-" + inttostring(t.GetDay())
+ " " + inttostring(t.GetHour()) + ":" + inttostring(t.GetMinute()) + ":" + inttostring(t.GetSecond());
//cout << mytime << endl;
static char sdate[30];
strcpy_s(sdate, mytime.c_str());
//cout << size(sdate) << endl;
return sdate;
}