unixODBC编程(九)分片查询长数据
访问www.tomcoding.com网站,学习Oracle内部数据结构,详细文档说明,下载Oracle的exp/imp,DUL,logminer,ASM工具的源代码,学习高技术含量的内容。
当一个表中有长数据类型的字段,比如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工具的源代码,还有实时数据库复制软件下载,学习高技术含量的内容。

浙公网安备 33010602011771号