C\C++开发MySQL程序简介(下)

2 篇文章 0 订阅
2 篇文章 0 订阅

如果需要向数据库中存储BLOB数据,则不能单纯的使用字符串,因为BLOB数据中很可能含有0。

一般有两种方法用来存储BLOB数据,一个是通过MYSQL提供的转义函数:

unsigned long mysql_real_escape_string(MYSQL *mysql, char *to, const char *from, unsigned long length)

该函数将“from”中的字符串编码为转义SQL字符串。将结果置于“to”中,并添加1个终结用NULL字节。编码的
字符为NUL (ASCII 0)、‘\n’、‘\r’、‘\’、‘'’、‘"’等。

注意,必须为“to”缓冲区分配至少length*2+1字节,以保证在最坏情况下不会溢出。


另一种方法则是通过MYSQL预处理函数进行BLOB数据的存储。

下面先介绍预处理函数。

MySQL客户端/服务器协议提供了预处理语句。该功能采用了由mysql_stmt_init()初始化函数返回的MYSQL_STMT语句处理程序数据结构。对于多次执行的语句,预处理执行是一种有效的方式。首先对语句进行解析,为执行作好准备。接下来,在以后使用初始化函数返回的语句句柄执行一次或多次。
对于多次执行的语句,预处理执行比直接执行快,主要原因在于,仅对查询执行一次解析操作。在直接执行的情况下,每次执行语句时,均将进行查询。此外,由于每次执行预处理语句时仅需发送参数的数据,从而减少了网络通信量。
预处理语句的另一个优点是,它采用了二进制协议,从而使得客户端和服务器之间的数据传输更有效率。
下述语句可用作预处理语句:CREATE TABLE、DELETE、DO、INSERT、REPLACE、SELECT、SET、UPDATE、以及大多数SHOW语句。在MySQL 5.1中,不支持其他语句。


预处理函数有两个核心的数据类型,MYSQL_STMT和MYSQL_BIND,关于MYSQL_STMT完全不需要理解,关于MYSQL_BIND需要查看下手册,接下来的一些函数需要用到它。

/*初始化,使用预处理语句必须先调用该函数*/
MYSQL_STMT *mysql_stmt_init(MYSQL *mysql);
/*准备语句*/
int mysql_stmt_prepare(MYSQL_STMT *stmt, const char *query, unsigned long length);
/*绑定参数*/
my_bool mysql_stmt_bind_param(MYSQL_STMT *stmt, MYSQL_BIND *bind);
/*绑定结果*/
my_bool mysql_stmt_bind_result(MYSQL_STMT *stmt, MYSQL_BIND *bind);
/*执行SQL语句*/
int mysql_stmt_execute(MYSQL_STMT *stmt);
/*使用完后需要释放资源*/
my_bool mysql_stmt_close(MYSQL_STMT *);

对于预处理流程,MYSQL提供了很多和普通流程同样的接口,比如获取记录集,获取一行记录,获取SQL语句影响的行数,以及错误处理函数等,只是在函数名中加入了stmt,查下手册就可以了。


这里稍微解释下mysql_stmt_prepare函数和mysql_stmt_bind_param函数,一般来说,需要使用到预处理流程的,都是SQL语句格式固定,只是有一两个值在变化,比如:

INSERT INTO mytbl VALUES(?,?,?)

这里的三个问号就是三个参数,如果你写过存储过程应该很好理解。


通过将问号字符“?”嵌入到SQL字符串的恰当位置,应用程序可包含SQL语句中的一个或多个参数标记符。

标记符仅在SQL语句中的特定位置时才是合法的。例如,它可以在INSERT语句的VALUES()列表中(为行指定列值),或
与WHERE子句中某列的比较部分(用以指定比较值)。但是,对于ID(例如表名或列名),不允许使用它们,不允许指定二进
制操作符(如等于号“=”)的操作数。后一个限制是有必要的,原因在于,无法确定参数类型。一般而言,参数仅在DML(数据
操作语言)语句中才是合法的,在DDL(数据定义语言)语句中不合法。


将这条语句prepare好后,就可以进行绑定参数了,当然在调用函数前,需要先将MYSQL_BIND结构体准备好,比如上边这条语句有3个参数,那么就需要准备一个数组

MYSQL_BIND bind[3]={0};
......
mysql_stmt_bind_param(stmt,bind);

再回到开头的问题,如果需要存储BLOB数据,那么我们可以设置MYSQL_BIND结构体绑定到一个buffer,然后执行SQL语句即可

MYSQL * mysql = NULL;
......
MSYQL_STMT * stmt = mysql_stmt_init(mysql);
const char * strSql = "insert into mytable(id,content) values(1,?)";
mysql_stmt_prepare(stmt,strSql,strlen(strSql));
char buffer[128]={0};
int len = 128;//数据的长度
/*通过memcpy等向buffer中复制数据*/
MYSQL_BIND bind;
bind.buffer_type = MYSQL_TYPE_BLOB;
bind.buffer = buffer;
bind.buffer_length = &len; //这个长度是指缓冲区的最大长度
bind.is_null = 0;
bind.length = &len;//这个指数据的实际长度

mysql_stmt_bind_param(stmt,&bind);
mysql_stmt_execute(stmt);
...
mysql_stmt_close(stmt);

不管使用普通流程还是预处理流程,在读取BLOB数据时,你需要用到下边的函数来获取数据的长度:

/*该函数返回一个指针,你可以通过索引值来获得相应的列的值的长度*/
/*每次获取一行新记录,你都需要调用该函数*/
unsigned long *mysql_fetch_lengths(MYSQL_RES *result);

下一篇将会给出一些比较完整的例子

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值