1、 Mysql预处理简介
预处理的意思是先提交sql语句到mysql服务端,执行预编译,客户端执行sql语句时,只需上传输入参数即可,这点和存储过程有点相似。
一般而言,预处理的执行效率相对于一般的sql执行操作,效率比较高。由于客户端上传的或是读取的结果集是绑定输入内存地址和输出内存地址,对于一些二进制流,或大数据量的存储和读取显得尤为方便。
2、 参考说明
具体的可以参考mysql的操作手册,里面第25章,C API库,里面有详细的说明。链接地址如下:http://dev.mysql.com/doc/refman/5.1/zh/apis.html#c-api-prepared-statements
3、以一个简单的sql查询语句来简要说明一下mysql预处理的功能。
调用mysql c api的预处理函数,执行预处理功能的步骤一般如下:
1) 先调用mysql_init(),初始化一个MYSQL对象,用于与数据库的链接句柄
2) 调用mysql_real_connect()链接数据库服务端
3) 调用mysql_stmt_init()初始化一个MYSQL_STMT对象,用于处理对应的预处理操作
4) 调用mysql_stmt_prepare()接口,上传预处理的sql语句
5) 定义相应的MYSQL_BIND数据结构,调用mysql_stmt_bind_param用于绑定输入参数
6) 如果有输出结果集,可以选择调用mysql_stmt_result_metadata()接口以结果集MYSQL_RES形式返回预处理语句元数据。
7) 调用mysql_stmt_execute()执行相应的sql查询操作
8) 如果有输出结果,调用mysql_stmt_bind_result将输出结果绑定到MYSQL_BIND数据结构对象上,同时调用mysql_stmt_store_result()将所有的结果集保存到客户端的缓冲区中,并通过mysql_stmt_fetch()来进行调用获取返回的每行的值
//初始化数据和链接句柄
MYSQL* pSql = new MYSQL;
Mysql_init(pSql);
MYSQL_STMT* pSql_Stmt = mysql_stmt_int(pSql);
//链接数据库
Mysql_read_connect(pSql, “127.0.0.1”, “root”, “123456”, “STMT”, NULL, 0);
//预处理的sql语句,后面的’?’表示输入参数
CString strSql = “Select Name, PhotoData from PhotoData where ID = ? “;
//准备字符串查询指向的sql语句
mysql_stmt_prepare(pSql_Stmt, strSql.Getbuffer(0), strSql.getlength());
//声明输入参数的绑定数据结构
MYSQL_BIND v_pParaBind[1]; //只有一个输入参数,绑定一个即可
My_Bool v_pParaIsNull[1]; //用于标明是输入还是输出
Unsigned long ParaLength[1]; //用于存储输入参数长度或输出结果长度
memset(v_pParaBind, 0, sizeof(v_pParaBind));
memset(v_pParaIsNull, 0, sizeof(v_pParaIsNull));
memset(Paralength, 0, sizeof(Paralength));
int nID = 18; //假定前面的那个select语句的输入参数为18
v_pParaBind [0].buffer = (char*)& nID;
v_pParaBind [0].buffer_length = sizeof(int);
Paralength[0] = sizeof(int);
v_pParaBind [0].length = &(Paralength[0]);
v_pParaBind [0].is_null = &( v_pParaIsNull [0]);
v_pParaBind [0].buffer_type = MYSQL_TYPE_LONG; //标明输入的类型是INT型
//绑定输入参数值
Mysql_stmt_bind_param(pSql_Stmt, v_pParaBind);
//执行sql查询操作
Mysql_stmt_execute(pSql_Stmt);
//绑定输出结果的MYSQL_BIND结构
MYSQL_BIND v_pResultBind[2]; //输出结果有两个数据列,定义两个BIND分别对应
My_bool v_pResultIsNull[2];
Unsigned long ResultLength[2];
char szName[200] = {0};
char szPhotoData[2000] = {0};
memset(v_pResultBind, 0, sizeof(v_pResultBind));
memset(v_pResultIsNull, 0, sizeof(v_pResultIsNull));
memset(ResultLength, 0, sizeof(ResultLength));
v_pResultBind[0].buffer = szName; //用于保存返回的结果数据
v_pResultBind[0].length = &(ResultLength[0]); //用于保存返回结果长度
v_pResultBind[0].is_null = &(v_pResultIsNull[0]);
v_pResultBind[0].buffer_type = MYSQL_TYPE_STRING;
v_pResultBind[1].buffer = szPhotoData;
v_pResultBind[1].length = &(ResultLength[1]);
v_pResultBind[1].is_null = &(v_pResultIsNull[1]);
v_pResultBind[1].buffer_type = MYSQL_TYPE_BLOB;
mysql_stmt_bind_result(pSql_Stmt, v_pResultBind);
//获取每行的值
Mysql_stmt_store_result(pSql_Stmt);
While(!mysql_stmt_fetch(pSql_Stmt))
{
If(!v_pResultIsNull[0])
{
Printf(“Name is %s, Name length is %d”, szName, ResultLength[0]);
}
If(!v_pResultIsNull[1])
{
Printf(“PhotoData length is %d”, ResultLength[0]);
//这里的PhotoData是二进制值,只能按长度位拷贝
}
}
//释放MYSQL_STMT和MYSQL对象
Mysql_stmt_close(pSql_Stmt);
pSql_Stmt = NULL;
Mysql_close(pSql);
pSql = NULL;
4、 mysql_stmt_send_long_data()函数
改函数用于将比较长的参数分几块依次传输给服务端,用法和上例一样,只是在绑定MYSQL_BIND参数值时,调用mysql_stmt_send_long_data(),传入BIND指向的参数每一块指针和长度,具体可见:
http://dev.mysql.com/doc/refman/5.1/zh/apis.html#mysql-stmt-send-long-data