unixODBC编程(九)分片查询长数据

当一个表中有长数据类型的字段,比如LONG数据类型,LONG RAW数据类型,字段存储的数据可能比较大,不可能在程序中定义这样大的缓冲区,这时就需要一部分一部分的读取数据,比如字段中存放了一个大的图片数据,现在取出来存储成一个图片文件,那么就可以定义一个合适的缓冲区,每次读取一部分数据,边读边写入文件。这时就需要用到一个函数SQLGetData(),先看一下函数原型和参数。

SQLRETURN SQLGetData(
      SQLHSTMT           StatementHandle,
      SQLUSMALLINT   Col_or_Param_Num,
      SQLSMALLINT      TargetType,
      SQLPOINTER        TargetValuePtr,
      SQLLEN                 BufferLength,
      SQLLEN *               StrLen_or_IndPtr);

StatementHandle是一个输入参数,查询语句的句柄。

Col_or_Param_Num是一个输入参数,结果集中列的编号,从1开始编号。

TargetType是一个输入参数,是列的数据类型对应的C语言类型。比如SQL_C_CHAR,SQL_C_SLONG,SQL_C_SSHORT,SQL_C_FLOAT等。

TargetValuePtr是一个输出参数,指向存储数据的缓冲区,不能为NULL。

BufferLength是一个输入参数,上面缓冲区的长度。

StrLen_or_IndPtr是一个输出参数,指示返回的数据长度,或空数据(SQL_NULL_DATA)。

这个函数要从结果集中取数据,所以需要游标在要取数的那行数据上,所以要在SQLFetch()或SQLFetchScroll()函数之后调用。

看一个实际的例子,有一个表叫做test_long1,有两个字段id和summary,id是整数类型,summary是LONG类型。从这个表中查询一条数据,id通过SQLBindCol()函数获取,summary通过SQLGetData()函数获取,代码如下。

#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "sql.h"
#include "sqlext.h"
#include "sqltypes.h"


SQLHANDLE       envh;           /* env handle */
SQLHANDLE       dbch;           /* connect handle */
SQLHANDLE       stmth;          /* statement handle */


int main(int argc, char *argv[])
{
    int                 conn = 0;
    SQLRETURN           rc;
    SQLLEN              rlen_ind1;
    SQLLEN              rlen_ind2;
    SQLINTEGER          id;
    char                dsn_str[32];
    char                usrname[32];
    char                passwd[32];
    char                sqltxt[128];
    char                buf[256];


    if (argc < 3) {
        fprintf(stderr, "usage: %s dsn username password\n", argv[0]);
        return (-1);
    }

    strncpy(dsn_str, argv[1], 32);
    dsn_str[31] = '\0';
    strncpy(usrname, argv[2], 32);
    usrname[31] = '\0';
    strncpy(passwd, argv[3], 32);
    passwd[31] = '\0';

    rc = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &envh);
    if (rc != SQL_SUCCESS) {
        fprintf(stderr, "Allocate environment handle error.\n");
        return (-1);
    }

    rc = SQLSetEnvAttr(envh, SQL_ATTR_ODBC_VERSION, (void *)SQL_OV_ODBC3, 0);
    if (rc != SQL_SUCCESS) {
        fprintf(stderr, "Set ODBC version error.\n");
        goto free_exit;
    }

    rc = SQLAllocHandle(SQL_HANDLE_DBC, envh, &dbch);
    if (rc != SQL_SUCCESS) {
        fprintf(stderr, "Allocate DB connection handle error.\n");
        goto free_exit;
    }

    rc = SQLSetConnectAttr(dbch, SQL_ATTR_LOGIN_TIMEOUT, (SQLPOINTER)10, 0);
    if (rc != SQL_SUCCESS) {
        fprintf(stderr, "Set connection timeout value error.\n");
        goto free_exit;
    }

    rc = SQLConnect(dbch, (SQLCHAR *)dsn_str, SQL_NTS, (SQLCHAR *)usrname, SQL_NTS,
        (SQLCHAR *)passwd, SQL_NTS);
    if (rc != SQL_SUCCESS) {
        fprintf(stderr, "Connect to DB error.\n");
        goto free_exit;
    }

    conn = 1;
    fprintf(stdout, "connect DB ok ......\n");

    rc = SQLAllocHandle(SQL_HANDLE_STMT, dbch, &stmth);
    if (rc != SQL_SUCCESS) {
        fprintf(stderr, "Allocate statment handle error.\n");
        goto free_exit;
    }

    sprintf(sqltxt, "select id, summary from test_long1 where id=11");
    rc = SQLPrepare(stmth, (SQLCHAR *)sqltxt, SQL_NTS);
    if (rc != SQL_SUCCESS) {
        fprintf(stderr, "Prepare statment error.\n");
        goto free_exit;
    }

    /* 执行语句,产生结果集 */
    rc = SQLExecute(stmth);
    if (rc != SQL_SUCCESS) {
        fprintf(stderr, "Execute statment error.\n");
        goto free_exit;
    }

    /* 绑定ID字段的输出变量 */
    rc = SQLBindCol(stmth, 1, SQL_C_ULONG, (SQLPOINTER)&id, 0, &rlen_ind1);
    if (rc != SQL_SUCCESS) {
        fprintf(stderr, "Bind column 1 error.\n");
        goto free_exit;
    }

    /* 调用SQLFetch()使得游标定位在第一条数据上,也就是我们要取数的数据行上 */
    rc = SQLFetch(stmth);

    if (rc == SQL_NO_DATA) {
        fprintf(stderr, "no data in result set.\n");
    } else if (rc == SQL_ERROR) {
        fprintf(stderr, "Fetch data error.\n");
        goto free_exit;
    } else if (rc == SQL_SUCCESS) {
        /* fetch成功,取得ID的值,下面通过SQLGetData()函数,一部分一部分的读取summary的值 */
        fprintf(stdout, "id=%d\nsummary:\n", id);

        while (1) {
            rc = SQLGetData(stmth, 2, SQL_C_CHAR, buf, 256, &rlen_ind2);
            if (rc == SQL_NO_DATA)
                break;

            if (rc == SQL_ERROR) {
                fprintf(stderr, "Get data from column error.\n");
                goto free_exit;
            }

            if (rc == SQL_SUCCESS) {
                /* 调用成功,打印这部分的数据 */
                fprintf(stdout, "%s\n", buf);
            }
        }
    }

    /* 关闭游标,游标可以隐式打开,但一定要显式关闭 */
    SQLCloseCursor(stmth);

    SQLFreeHandle(SQL_HANDLE_STMT, stmth);

    SQLDisconnect(dbch);

    SQLFreeHandle(SQL_HANDLE_DBC, dbch);

    SQLFreeHandle(SQL_HANDLE_ENV, envh);

    return (0);

free_exit:
    if (stmth != NULL) {
        SQLFreeHandle(SQL_HANDLE_STMT, stmth);
    }

    if (conn) {
        SQLDisconnect(dbch);
    }

    if (dbch != NULL) {
        SQLFreeHandle(SQL_HANDLE_DBC, dbch);
    }

    if (envh != NULL) {
        SQLFreeHandle(SQL_HANDLE_ENV, envh);
    }

    return (-1);
}

访问www.tomcoding.com网站,学习Oracle内部数据结构,详细文档说明,下载Oracle的exp/imp,DUL,logminer,ASM工具的源代码,学习高技术含量的内容。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值