收集整理了一份《2024年最新物联网嵌入式全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升的朋友。
需要这些体系化资料的朋友,可以加我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年最新物联网嵌入式全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升的朋友。
需要这些体系化资料的朋友,可以加我V获取:vip1024c (备注嵌入式)
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人
都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
et/topics/618679757)**
需要这些体系化资料的朋友,可以加我V获取:vip1024c (备注嵌入式)
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人
都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!