SQLBindParameter

  使用ODBC 3.0开发,在Blob数据绑定时,Statement类封装了一个方法:

void setBlob(int iParam, Blob *b){

    SDWORD len = SQL_LEN_DATA_AT_EXEC(b->getLength());

    retcode = retcode = SQLBindParameter(this->hstmt, iParam, SQL_PARAM_INPUT,
        SQL_C_BINARY, SQL_LONGVARBINARY, b->getLength(), 0,
        (void*)b, b->getLength(), &len);

}

  同时,又封装了一个executeUpdate方法:

bool executeUpdate(){
    SQLPOINTER data;char buf[4 * 1024] = {0};
    retcode = ::SQLExecute(hstmt);
    if(retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO)
        retcode = ::SQLParamData(hstmt, &data);
    while(retcode == SQL_NEED_DATA){
        Blob *b = (Blob*)data;
        while(true){
            SQLLEN blen = b->getBuffer(buf, 4 * 1024);
            if(blen == 0) break;
            retcode = ::SQLPutData(hstmt, (SQLPOINTER)buf, blen);
            if(retcode != SQL_SUCCESS)
                throw CSQLException(retcode, getErrorMessage());
        }
        retcode = ::SQLParamData(hstmt, &data);
    }
    if(retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO)
        throw CSQLException(retcode, getErrorMessage());
    return true;
}

  结果,执行executeUpdate时出现“[Microsoft][ODBC SQL Server Driver]字符串数据,长度不匹配”的错误。


  找了半天,没有发现什么逻辑错误,后来一次偶然的机会在网络上看到类似的代码,它的写法是这样的:

    SDWORD len;

    retcode = retcode = SQLBindParameter(this->hstmt, iParam, SQL_PARAM_INPUT,
        SQL_C_BINARY, SQL_LONGVARBINARY, b->getLength(), 0,
        (void*)b, b->getLength(), &len);

    len = SQL_LEN_DATA_AT_EXEC(b->getLength());

  其中,len是之后才赋值的,并且这段代码与后续execute代码在同一个方法体内。


  由此可见,其实传进去的这个len指针是在SQLPutData时才真正起作用,因此要保证在SQLPutData时它的值有效且正确。


  至此才真正发现原因,原来还是犯了低级错误:由于len是setBlob方法的内部变量,因此当SQLBindParameter返回之后,它的地址就无效了,而后面调用executeUpdate时就会出错(至少是长度不对,也可能比较严重,内存不能访问)。


  之后将SDWORD len;改为SDWORD *len = new SDWORD();,然后再赋值就可以了。但有一点小Bug,就是会有内存泄漏(可以考虑使用类来封装,比如放在Blob类中来下定义,这样就不要额外分配内存单元,不便于回收)。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值