C操作MYSQL数据库

收集整理了一份《2024年最新物联网嵌入式全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升的朋友。
img
img

如果你需要这些资料,可以戳这里获取

需要这些体系化资料的朋友,可以加我V获取:vip1024c (备注嵌入式)

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人

都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

MYSQL_STMT *pstmt = mysql_stmt_init(&m_sqlCon);				//全局变量。使用完后记得调用mysql_stmt_close()释放!
string stmtSql = "insert into `tableName` values(?,?,?,?)";			//SQL语句。
mysql_stmt_prepare(pstmt, stmtSql.c_str(), stmtSql.length());		//绑定SQL语句到MYSQL_STMT变量中,也就是之后再执行该SQL操作直接用MYSQL_STMT变量就行了,不用再重复写该SQL语句了。类似预编译一样。
MYSQL_BIND bindStmt[4];															//insert操作,要插入几个字段值数组就多大。这里4个字段值。MYSQL_BIND结构体存储字段的一些信息,比如值,是否为非负,非空等。
char filed1 = 'a';
int filed2 = 1;
float filed3 = 2.2;
char filed4[] = "123";
memset(bindStmt, 0, sizeof(bindStmt));										//初始化为0
bindStmt[0].buffer_type = MYSQL_TYPE_TINY;							//char字段类型。
bindStmt[0].buffer = &filed1;														//注意赋的是地址而不是值。
bindStmt[0].buffer_length = sizeof(filed1);									//buffer的字节个数
bindStmt[1].buffer_type = MYSQL_TYPE_LONG;						//int类型
bindStmt[1].buffer = &filed2;
bindStmt[1].buffer_length = sizeof(filed2);
bindStmt[2].buffer_type = MYSQL_TYPE_FLOAT;
bindStmt[2].buffer = &filed3;
bindStmt[2].buffer_length = sizeof(filed3);
bindStmt[3].buffer_type = MYSQL_TYPE_STRING;
bindStmt[3].buffer = filed4;
bindStmt[3].buffer_length = sizeof(filed4);
mysql_stmt_bind_param(pstmt,  bindStmt);									//绑定字段值到MYSQL_STMT中。
if(mysql_stmt_execute(pstmt) != 0)												//执行SQL操作。
{
	unsigned int errCode = mysql_errno(&m_sqlCon);					//查看错误信息。
	if(errCode==2014)
	{
		//Commands were executed in an improper order.
	}
	else if(errCode==2006)
	{
		//The MySQL server has gone away.
	}
	else if(errCode==2013) 
	{
		//The connection to the server was lost during the query.;
	}
	else if(errCode==2000) 
	{
		//An unknown error occurred.;
	}
	mysql_ping(&m_sqlCon);
}

调用mysql_stmt_init()申请的MYSQL_STMT变量用完后记得调用mysql_stmt_close()释放,不要用一次释放一次,应该等不需要再执行该SQL操作时再释放。有多少需要频繁操作的SQL语句就可以申请多少MYSQL_STMT变量。这种方式不能在一条语句中执行多SQL操作。MYSQL_BIND结构体主要用到的属性有:

struct MYSQL_BIND
{
	enum enum_field_types buffer_type;					//字段值类型,具体类型查看API文档。
	void *buffer;														//需要赋值的变量地址。
	unsigned long buffer_length;							//buffer指向变量的字节个数。
	unsigned long *length;										//指向实际字节个数。
	my_bool *is_null;												//是否为空。
	my_bool is_unsigned;										//是否为非负数。
	......
}

3.读数据库

第一种方式

string sql = "select * from `" + tableName + "`";					//SQL语句,读取表中所有数据。
mysql_real_query(&m_sqlCon, sql.c_str(), sql.length());				//执行SQL语句。
MYSQL_RES *sqlRes = mysql_store_result(&m_sqlCon);					//查询结果集。还可以使用mysql_use_result(&m_sqlCon);
if (sqlRes)
{
	MYSQL_ROW sqlRow;						//typedef char **MYSQL_ROW,就是个二维字符数组,所以读取的字段值都是字符串形式的。
	int colums = mysql_num_fields(sqlRes);			//列数
	while (sqlRow = mysql_fetch_row(sqlRes))		//每次取出一行数据。
	{
		for(int i=0; i<colums; i++)
		{
			 string value(sqlRow[i]);				//字段值。
		}
	}
	mysql_free_result(sqlRes);					//释放结果集。
}

常用的查询结果集是mysql_store_result(),可以调用mysql_num_rows()获取行数,并且可以调用mysql_data_seek()或mysql_row_seek()改变当前行,缺点是需要足够的内存。如果查询的数据量很大,建议使用mysql_use_result(),每次只查询一行数据,所以占用内存少,但是缺点是不能获取行数,并且必须读取完所有行。
prepared statement方式

MYSQL_STMT *stmt;
int num_fields;       //列数。
MYSQL_FIELD *fields;  	//列字段信息。
MYSQL_BIND *rs_bind;  //存储字段值信息。
int data1;					//存储字段值。
float data2;				//存储字段值。
char data3[20];			//存储字段值。

stmt = mysql_stmt_init(&m_sqlCon);
string sql = "select * from `" + tableName + "`";					//SQL语句,读取表中所有数据。
mysql_stmt_prepare(stmt, sql.c_str(), sql.length());				//绑定SQL语句。
mysql_stmt_execute(stmt) ;										//执行SQL语句。
num_fields = mysql_stmt_field_count(stmt);			//获取列数。
if (num_fields > 0)
{
    MYSQL_RES *rs_metadata = mysql_stmt_result_metadata(stmt);				//获取结果集。
    fields = mysql_fetch_fields(rs_metadata);							//获取所有字段信息。可以编写万能查询操作,类似反射。
    rs_bind = (MYSQL_BIND *) malloc(sizeof (MYSQL_BIND) * num_fields);		//根据字段值个数开辟MYSQL_BIND空间。
    memset(rs_bind, 0, sizeof (MYSQL_BIND) * num_fields);
    for (int i = 0; i < num_fields; ++i)										//根据字段信息设置MYSQL_BIND。
    {
      rs_bind[i].buffer_type = fields[i].type;								//字段类型。
      switch (fields[i].type)
      {
        case MYSQL_TYPE_LONG:													//整型。
          rs_bind[i].buffer = (char *) &(data1);								//字段值存储在data1中。
          rs_bind[i].buffer_length = sizeof (data1);
          break;
		case MYSQL_TYPE_FLOAT:								//单精度浮点型float。
		  rs_bind[i].buffer = (char *)&(data2);				//字段值存储在data2中。
		  rs_bind[i].buffer_length = sizeof (data2);
          break;
        case MYSQL_TYPE_CHAR:										//字符串。
		  rs_bind[i].buffer = data3;					//字段值存储在data3中。
		  rs_bind[i].buffer_length = sizeof (data3);
          break;
        default:
          break;
      }
    }
	mysql_stmt_bind_result(stmt, rs_bind);				//绑定MYSQL_BIND。
    while (mysql_stmt_fetch(stmt))						//每次获取一行。
    {
     	//data1,data2,data3存储了字段值。
    }
    mysql_free_result(rs_metadata);					//释放结果集。
    free(rs_bind);								//释放MYSQL_BIND空间。
  }

结语

除了使用API操作MYSQL外,还可以使用MYSQL Connector/C,具体信息就去看MYSQL官方文档吧。

收集整理了一份《2024年最新物联网嵌入式全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升的朋友。
img
img

如果你需要这些资料,可以戳这里获取

需要这些体系化资料的朋友,可以加我V获取:vip1024c (备注嵌入式)

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人

都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

et/topics/618679757)**

需要这些体系化资料的朋友,可以加我V获取:vip1024c (备注嵌入式)

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人

都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值