C++下,MySql预处理封装

本文介绍了一种C++环境下MySQL预编译语句的封装方法。通过预编译技术,实现了SQL语句的参数化,提高了执行效率,并增强了安全性。文章提供了具体的类定义和示例代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

C++下,MySql预处理封装

为什么要使用预处理

1、即时 SQL

一条 SQL 在 DB 接收到最终执行完毕返回,大致的过程如下:
  1. 词法和语义解析;
  2. 优化 SQL 语句,制定执行计划;
  3. 执行并返回结果;
  如上,一条 SQL 直接是走流程处理,一次编译,单次运行,此类普通语句被称作Immediate Statements (即时 SQL)。

2、预处理 SQL

  但是,绝大多数情况下,某需求某一条 SQL 语句可能会被反复调用执行,或>者每次执行的时候只有个别的值不同(比如 select 的 where 子句值不同,update 的 set 子句值不同,insert 的 values 值不同)。如果每次都需要经过上面的词法语义解析、语句优化、制定执行计划等,则效率就明显不行了。
  所谓预编译语句就是将此类 SQL 语句中的值用占位符替代,可以视为将 SQL 语句模板化或者说参数化,一般称这类语句叫Prepared Statements。
  预编译语句的优势在于归纳为:一次编译、多次运行,省去了解析优化等过程;此外预编译语句能防止 SQL 注入。

SqlStmt类

上面那段抄的,主要看下面这里。
鉴于预编译使用的繁琐,我将将其做了封装,由于是我个人项目用的,封装具有局限性,使用此类需要注意以下几点:
  1. 此类 get 数据 仅返回一条,需要做返回全部数据的请自行修改。
  2. 带入和返回的参数只能是 std::string 类型,需要其他类型请自行封装,注意写入参数时,传入的是地址,例如 int 类型用 &int。
  3. results 中返回的字符串类型需要用 .c_str() 方法 才能获取正确的结果。
  4. 我这个类封装的没有实现效率提升,需要的话可以把语句做成常量,然后在初始化的时候上传到服务器,然后保存句柄,用到时候直接调用就行。

// SqlStmt.h
#pragma once

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

class SqlStmt
{
private:
	MYSQL_STMT* stmt;
public:

	int connect(MYSQL& mysql, std::string host, std::string user, std::string passwd, std::string db, unsigned int port, std::string unix_socket, unsigned long clientflag);
	int close(MYSQL& conn);

	/*
	* 插入set的setData数据进table表
	*/
	bool insert_table_info(MYSQL& conn, std::string table, 
		std::string set, std::string setData);

	/*
	* 插入set1的setData1和set2的setData2数据进table表
	*/
	bool insert_table_info(MYSQL& conn, std::string table, 
		std::string set1, std::string setData1, 
		std::string set2, std::string setData2);

	/*
	* 获取table表来自where的whereData数据对应的from的数据
	*/
	std::string get_table_info(MYSQL& conn, std::string table, 
		std::string from, 
		std::string where, std::string whereData);

	/*
	* 设置table表来自where的whereData数据对应的set数据为setData
	*/
	bool set_table_info(MYSQL& conn, std::string table,
		std::string set, std::string setData,
		std::string where, std::string whereData);

	/*
	* 删除table表来自where的whereData数据对应的记录
	*/
	bool delete_table_info(MYSQL& conn, std::string table, 
		std::string where, std::string whereData);
};
// SqlStmt.cpp
#include "SqlStmt.h"

int SqlStmt::connect(MYSQL& conn, std::string host, std::string user, std::string passwd, std::string db, unsigned int port, std::string unix_socket = NULL, unsigned long clientflag = 0)
{
    // 初始化句柄
    mysql_init(&conn);
    // 连接的数据库(句柄、主机名、用户名、密码、数据库名、端口号、socket指针、标记)
    if (!mysql_real_connect(&conn, host.c_str(), user.c_str(), passwd.c_str(), db.c_str(), port, nullptr, 0))
    {
        return -1;
    }
    else {
        return 0;
    }
    
}

int SqlStmt::close(MYSQL& conn)
{
    if (!mysql_ping(&conn)) // 连接存活
    {
        mysql_close(&conn);
        return 0;
    }
    else {
        return -1;
    }
    
}

bool SqlStmt::insert_table_info(MYSQL& conn, std::string table, std::string set, std::string setData)
{
    mysql_query(&conn, "SET NAMES GB2312"); // 适配中文
    bool flag = false;
    stmt = mysql_stmt_init(&conn); //创建MYSQL_STMT句柄
    if (!stmt) {
        return false;
    }

    // 构建语句
    std::string query = "INSERT INTO " + table + " (" + set + ") VALUES (?);";
    // 发送到服务器
    if (mysql_stmt_prepare(stmt, query.c_str(), query.size()))
    {
        return false;
    }

    MYSQL_BIND params[1];   // 参数
    memset(params, 0, sizeof(params));
    params[0].buffer_type = MYSQL_TYPE_STRING;
    params[0].buffer = (char*)setData.c_str();
    params[0].buffer_length = setData.size();

    // 绑定 获取结果的绑定见get_table_info()方法
    mysql_stmt_bind_param(stmt, params);

    if (!mysql_stmt_execute(stmt)) {
        flag = true;
    }
    else {
        flag = false;
    }

    mysql_stmt_close(stmt);

    return flag;
}

bool SqlStmt::insert_table_info(MYSQL& conn, std::string table, std::string set1, std::string setData1, std::string set2, std::string setData2)
{
    mysql_query(&conn, "SET NAMES GB2312");
    bool flag = false;
    stmt = mysql_stmt_init(&conn);
    if (!stmt) {
        return false;
    }

    std::string query = "INSERT INTO " + table + " (" + set1 + "," + set2 + ") VALUES (?,?);";
    if (mysql_stmt_prepare(stmt, query.c_str(), query.size()))
    {
        return false;
    }

    MYSQL_BIND params[2]; 
    memset(params, 0, sizeof(params));
    params[0].buffer_type = MYSQL_TYPE_STRING;
    params[0].buffer = (char*)setData1.c_str();
    params[0].buffer_length = setData1.size();

    params[1].buffer_type = MYSQL_TYPE_STRING;
    params[1].buffer = (char*)setData2.c_str();
    params[1].buffer_length = setData2.size();

    mysql_stmt_bind_param(stmt, params);

    if (!mysql_stmt_execute(stmt)) {
        flag = true;
    }
    else {
        flag = false;
    }

    mysql_stmt_close(stmt);

    return flag;
}

std::string SqlStmt::get_table_info(MYSQL& conn, std::string table, std::string from, std::string where, std::string whereData)
{
    mysql_query(&conn, "SET NAMES GB2312");
    std::string result = "";
    stmt = mysql_stmt_init(&conn); 
    if (!stmt) {
        return NULL;
    }

    std::string query = "SELECT " + from + " FROM " + table + " WHERE " + where + " = ?;";
    if (mysql_stmt_prepare(stmt, query.c_str(), query.size()))
    {
        return NULL;
    }

    MYSQL_BIND params[1];  
    MYSQL_BIND results[1];   // 结果
    memset(params, 0, sizeof(params));
    params[0].buffer_type = MYSQL_TYPE_STRING;
    params[0].buffer = (char*)whereData.c_str();
    params[0].buffer_length = whereData.size();

    memset(results, 0, sizeof(results));
    results[0].buffer_type = MYSQL_TYPE_STRING;
    results[0].buffer = (char*)result.c_str();
    results[0].buffer_length = MYSQL_TYPE_STRING;

    mysql_stmt_bind_param(stmt, params);
    mysql_stmt_bind_result(stmt, results);
    mysql_stmt_execute(stmt);        

    mysql_stmt_store_result(stmt);     

    if (mysql_stmt_fetch(stmt) != 0)
        return NULL;

    mysql_stmt_close(stmt);

    return result.c_str();
}

bool SqlStmt::set_table_info(MYSQL& conn, std::string table, std::string set, std::string setData, std::string where, std::string whereData)
{
    mysql_query(&conn, "SET NAMES GB2312");
    bool flag = false;

    stmt = mysql_stmt_init(&conn);
    if (!stmt) {
        return false;
    }

    std::string query = "UPDATE " + table + " SET " + set + " = ? WHERE " + where + " = ?;";
    if (mysql_stmt_prepare(stmt, query.c_str(), query.size()))
    {
        return false;
    }

    MYSQL_BIND params[2];   
    memset(params, 0, sizeof(params));
    params[0].buffer_type = MYSQL_TYPE_STRING;
    params[0].buffer = (char*)setData.c_str();
    params[0].buffer_length = setData.size();

    params[1].buffer_type = MYSQL_TYPE_STRING;
    params[1].buffer = (char*)whereData.c_str();
    params[1].buffer_length = whereData.size();

    mysql_stmt_bind_param(stmt, params);

    if (!mysql_stmt_execute(stmt)) {
        flag = true;
    }
    else {
        flag = false;
    }
    mysql_stmt_close(stmt);

    return flag;
}

bool SqlStmt::delete_table_info(MYSQL& conn, std::string table, std::string where, std::string whereData)
{
    mysql_query(&conn, "SET NAMES GB2312");
    bool flag = false;
    stmt = mysql_stmt_init(&conn);
    if (!stmt) {
        return false;
    }

    std::string query = "DELETE FROM " + table + " WHERE " + where + " = ?;";
    if (mysql_stmt_prepare(stmt, query.c_str(), query.size()))
    {
        return flag;
    }

    MYSQL_BIND params[1];   
    memset(params, 0, sizeof(params));
    params[0].buffer_type = MYSQL_TYPE_STRING;
    params[0].buffer = (char*)whereData.c_str();
    params[0].buffer_length = whereData.size();

    mysql_stmt_bind_param(stmt, params);
    mysql_stmt_execute(stmt);          

    if (mysql_stmt_store_result(stmt) == 0) {     
        flag = true;
    }
    else {
        flag = false;
    }

    mysql_stmt_close(stmt);

    return flag;
}
// 示例
#include "SqlStmt.h"
#include "mysql.h"

int main(void) {

	SqlStmt mysqlstmt;
	MYSQL conn;

	// 连接数据库
	mysqlstmt.connect(conn, "localhost", "root", "123456", "db", 3306);

	// 插入,王二狗诞生
	mysqlstmt.insert_table_info(conn, "user_info", "name", "王二狗", "sex", "男");

	// 更新,王二狗变性后,重新更新他的性别。
	mysqlstmt.set_table_info(conn, "user_info", "sex", "女", "name", "王二狗");

	// 获取,得到王二狗的性别
	std::string sex = mysqlstmt.get_table_info(conn, "user_info", "sex", "name", "王二狗");

	// 删除,王二狗没了
	mysqlstmt.delete_table_info(conn, "user_info", "name", "王二狗");

	// 关闭数据库
	mysqlstmt.close(conn);

	return 0;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值