C操作MYSQL数据库
/绑定字段值到MYSQL_STMT中。
my_bool mybool = true; //typedef char my_bool,其实就是数据库的bool类型
mysql_options(&m_sqlCon, MYSQL_OPT_RECONNECT, &mybool); //开启自动重连(注意自动重连也是要调用mysql_ping()函数才会重连的),mysql_options函数可以配置数据库各种参数,比如传输的包大小,开启多SQL语句执行,读写超时时间等,总之可以优化数据库。
if (mysql_real_connect(&m_sqlCon, host, name, passwd, db, 3306, NULL, CLIENT_MULTI_STATEMENTS)) //连接数据库。3306是数据库端口号,CLIENT_MULTI_STATEMENTS为开启多SQL语句执行。
else
{
switch(mysql_errno(&m_sqlCon)) //连接数据库失败,查看错误信息。这里只列出了三个错误信息。
{
case CR_CONNECTION_ERROR: break; //Failed to connect to the MySQL server.
case CR_UNKNOWN_HOST: break; //Failed to find the IP address for the host name.
case CR_VERSION_ERROR: break; //A protocol mismatch resulted from attempting to connect to a server with a client library that uses a different protocol version.
default: break;
}
}
要说明的都在注释中了。MySQL API提供了两种方式操作数据库,一种是mysql\_real\_query()函数执行SQL语句,另外一种就是prepared statement方式了。第一种方式使用起来很简单,就是把字符串类型SQL语句作为参数调用mysql\_real\_query()函数执行就行了。prepared statement方式对于频繁操作数据库有优势,具体使用哪种根据实际效率看吧。以下操作都会介绍两种方式。
### 2.写数据库
**第一种方式:**
string sql = “insert into tableName values(1, ‘2’, …)”; //就是简单的SQL语句而已,但是这里有两点要注意!表名两边加上`符号(Tab键上面的那个键也就是1键左边的键),字段值是字符或字符串类型的话两边要加’符号。
if(mysql_real_query(&m_sqlCon, sql.c_str(), sql.length())!=0) //执行SQL语句,一个函数就实现了各种操作。执行成功返回0。
{
unsigned int errCode = mysql_errno(&m_sqlCon); //查看错误信息
if(errCode2014)
{
//Commands were executed in an improper order.
}
else if(errCode2006)
{
//The MySQL server has gone away.;
}
else if(errCode2013)
{
//The connection to the server was lost during the query.;
}
else if(errCode2000)
{
//An unknown error occurred.;
}
mysql_ping(&m_sqlCon); //检查数据库是否断开,如果断开就重连并且执行上一条出错的SQL语句。
}
第一种方式太简单了,直接调用mysql\_real\_query()执行各种SQL语句。但是要注意两点,SQL语句中表名两边加上`符号(Tab键上面的那个键也就是1键左边的键),字段值是字符或字符串类型的话两边要加’符号。
**prepared statement方式**
对于频繁执行的SQL语句,绑定到MYSQL\_STMT类型变量中,类似预编译一样,其中原理查看API文档说明吧。首先调用mysql\_stmt\_init()函数申请MYSQL\_STMT类型变量,然后调用mysql\_stmt\_prepare()函数绑定SQL语句,需要带值的SQL语句比如insert操作还需要调用mysql\_stmt\_bind\_param()函数绑定值。字段值信息由MYSQL\_BIND结构体存储。过程如下:
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(errCode2014)
{
//Commands were executed in an improper order.
}
else if(errCode2006)
{
//The MySQL server has gone away.
}
else if(errCode2013)
{
//The connection to the server was lost during the query.;
}
else if(errCode2000)
{
//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++)
{
一个人可以走的很快,但一群人才能走的更远。有问题欢迎添加作者徽【vip1024c】技术交流、学习资源、职场吐槽、大厂内推、面试辅导,让我们一起学习成长!
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空间。
}
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐



所有评论(0)