有分片插入的操作,就会有分片查询的操作,分片插入用OCI_DATA_AT_EXEC模式来绑定输入变量,分片查询需要用到OCI_DYNAMIC_FETCH模式来定义输出变量。分片查询的步骤如下。
1. 分片OCI语句句柄。
2. 准备SQL语句,语法分析。
3. 定义输出变量,输出变量为空指针,运行时再提供缓冲区。使用OCI_DYNAMIC_FETCH模式。
4. 执行查询语句。
5. 执行OCIStmtFetch()函数,这时会返回OCI_NEED_DATA。
6. 执行OCIStmtSetPieceInfo()函数,指定接收数据的缓冲区地址和缓冲区大小。
7. 再执行OCIStmtFetch()函数,这时接收缓冲区中会有返回的数据,如果没有后续的数据了,Fetch函数会返回OCI_SUCESS,整个分片查询结束,如果还有剩余数据,Fetch函数还会返回OCI_NEED_DATA,这时跳到第6步,继续执行。
我们把上一次插入的数据再读出来,使用分片查询的步骤,请看完整的代码。
OCIEnv *envhp = NULL;
OCIError *errhp = NULL;
OCIServer *svrhp = NULL;
OCISession *usrhp = NULL;
OCISvcCtx *svchp = NULL;
OCIStmt *smthp = NULL;
/* 分片查询LONG数据 */
int select_long_piece(void)
{
sword rc;
int slen;
sb2 ind_info;
ub4 alen_info;
ub2 rcode_info;
OCIDefine *defp;
char sqltxt[1024];
char long_buf[4096];
/* 分配OCI语句句柄 */
rc = OCIHandleAlloc(
(void *)envhp,
(void **)&smthp,
OCI_HTYPE_STMT,
0,
(void **)NULL
);
if (rc != OCI_SUCCESS) {
fprintf(stderr, "OCIHandleAlloc() - allocate statement handle error !\n");
return (-1);
}
/* 生成SQL语句文本 */
strcpy(sqltxt, "SELECT INFO FROM test_long_tab WHERE ID=1");
slen = strlen(sqltxt);
/* 准备语句 */
if (check_oci_error(errhp,
OCIStmtPrepare(smthp, errhp, (const OraText *)sqltxt, slen,
OCI_NTV_SYNTAX, OCI_DEFAULT)) < 0)
return (-1);
/* 定义INFO的输出变量,使用NULL值,使用OCI_DYNAMIC_FETCH模式,
* value_sz要设置成读取数据的最大值
*/
if (check_oci_error(errhp,
OCIDefineByPos((OCIStmt *)smthp,
(OCIDefine **)&defp,
errhp,
(ub4)1, /* position */
(void *)NULL, /* valuep */
(sb4)0x7FFFFFFF, /* value_sz */
(ub2)SQLT_LNG, /* dty */
(void *)NULL, /* indp */
(ub2 *)NULL, /* alenp */
(ub2 *)NULL, /* column return code pointer */
(ub4)0, /* maxarr_len */
(ub4 *)NULL, /* curelep */
(ub4)OCI_DYNAMIC_FETCH)
) < 0)
return (-1);
/* 执行OCI语句 */
if (check_oci_error(errhp,
OCIStmtExecute(svchp,
smthp, /* stmthp */
errhp, /* errhp */
0, /* iters */
0, /* rowoff */
NULL, /* snap_in */
NULL, /* snap_out */
OCI_DEFAULT) /* mode */
) < 0)
return (-1);
/* 循环处理获取的数据,在这里为了方便,只把数据长度打印出来 */
while (1) {
if ((rc = check_oci_error(errhp,
OCIStmtFetch(smthp, errhp, 1, OCI_FETCH_NEXT, OCI_DEFAULT))) < 0)
return (-1);
if (rc == OCI_SUCCESS) {
/* 返回数据完毕,退出循环,注意这里还有数据,要处理掉 */
fprintf(stdout, "data actual length: %d\n", alen_info);
break;
}
if (rc != OCI_NEED_DATA) {
fprintf(stderr, "data fetch not completed !\n");
return (-1);
}
/* 处理数据 */
fprintf(stdout, "data actual length: %d\n", alen_info);
/* 设置数据片信息,alen_info设置一次返回的最大数据量 */
alen_info = 4000;
if (check_oci_error(errhp,
OCIStmtSetPieceInfo((void *)defp, OCI_HTYPE_DEFINE,
errhp, (const void *)long_buf, &alen_info,
OCI_ONE_PIECE, (const void *)&ind_info, &rcode_info)
) < 0)
return (-1);
}
return (0);
}