查询数据是OCI程序中的一个常用的操作,它不会对数据库的数据产生改变,操作的步骤也与更新操作的步骤有区别,用到了不一样的函数。下面先看一下查询操作的步骤。
1. 分配OCI语句句柄,用到函数OCIHandleAlloc()。
2. 准备SQL语句,用到函数OCIStmtPrepare()。
3. 定义每个查询字段输出变量,用到函数OCIDefineByPos()。
4. 执行OCI语句,用到函数OCIStmtExecute()。
5. 取回查询结果,用到函数OCIStmtFetch()。
下面看一下用到的新函数原型和参数。
第一个函数,定义输出变量函数。
sword OCIDefineByPos ( OCIStmt *stmtp,
OCIDefine **defnpp,
OCIError *errhp,
ub4 position,
void *valuep,
sb4 value_sz,
ub2 dty,
void *indp,
ub2 *rlenp,
ub2 *rcodep,
ub4 mode );
stmtp是一个输入/输出参数,是分配的查询语句句柄。
defnpp是一个输入/输出参数,是跟查询列表中的字段对应的定义句柄,存放本字段相关的信息,如果不需要,可以赋值为NULL。
errhp是一个输入/输出参数,是错误句柄,用于获取错误码和错误信息文本。
position是一个输入参数,是查询列表中字段的位置,从1开始计算。
valuep是一个输入/输出参数,指向输出变量的地址或一个输出数组的地址。
value_sz是一个输入参数,指定valuep存储缓冲区的大小,以字节计算。
dty是一个输入参数,是查询列表中字段的数据类型,与绑定函数中的定义一致。
indp是一个输入参数,是指示变量指针,如果查询的字段返回值为NULL,指示变量返回值为-1。
rlenp是一个输入/输出参数,是返回结果的字段值的实际大小。
rcodep是一个输出参数,返回字段级别的错误码。
mode是一个输入参数,指示定义函数的模式,一般取值为OCI_DEFAULT。
第二个函数,取回查询结果函数。
sword OCIStmtFetch ( OCIStmt *stmtp,
OCIError *errhp,
ub4 nrows,
ub2 orientation,
ub4 mode );
stmtp是一个输入参数,查询语句的OCI句柄。
errhp是一个输入参数,错误句柄,用于返回错误码和错误信息文本。
nrows是一个输入参数,希望取回的数据条数。
orientation是一个输入参数,获取数据的方向,取值为OCI_FETCH_NEXT,获取下一条数据。
mode是一个输入参数,取值为OCI_DEFAULT。
我们还是通过一个实际的例子来看看这些函数的用法,还是使用前面创建的表test_tab,从里面查询数据的SQL语句为SELECT ID, NAME, ADDR FROM test_tab。其中ID, NAME, ADDR就是查询列表字段。下面看看用OCI程序怎样操作。
OCIEnv *envhp = NULL;
OCIError *errhp = NULL;
OCIServer *svrhp = NULL;
OCISession *usrhp = NULL;
OCISvcCtx *svchp = NULL;
OCIStmt *smthp = NULL;
/* 查询数据 */
int select_data(void)
{
sword rc;
int slen;
sb2 ind_id;
sb2 ind_name;
sb2 ind_addr;
ub2 alen_id;
ub2 alen_name;
ub2 alen_addr;
ub2 rcode_id;
ub2 rcode_name;
ub2 rcode_addr;
int32_t id;
char id_str[64];
char name[32];
char addr[256];
OCIDefine *defp;
char sqltxt[1024];
/* 分配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);
}
/* 生成查询语句文本 */
strcpy(sqltxt, "SELECT ID, NAME, ADDR FROM test_tab");
slen = strlen(sqltxt);
/* 准备语句 */
if (check_oci_error(errhp,
OCIStmtPrepare(smthp, errhp, (const OraText *)sqltxt, slen,
OCI_NTV_SYNTAX, OCI_DEFAULT)) < 0)
return (-1);
/* 定义第一个字段ID的输出变量 */
if (check_oci_error(errhp,
OCIDefineByPos((OCIStmt *)smthp,
(OCIDefine **)&defp,
errhp,
(ub4)1, /* position */
(void *)&id, /* valuep */
(sb4)4, /* value_sz */
(ub2)SQLT_INT, /* dty */
(void *)&ind_id, /* indp */
(ub2 *)&alen_id, /* alenp */
(ub2 *)&rcode_id, /* column return code pointer */
(ub4)OCI_DEFAULT) /* mode */
) < 0)
return (-1);
/* 定义第二个字段NAME的输出变量 */
if (check_oci_error(errhp,
OCIDefineByPos((OCIStmt *)smthp,
(OCIDefine **)&defp,
errhp,
(ub4)2, /* position */
(void *)name, /* valuep */
(sb4)30, /* value_sz */
(ub2)SQLT_STR, /* dty */
(void *)&ind_name, /* indp */
(ub2 *)&alen_name, /* alenp */
(ub2 *)&rcode_name, /* column return code pointer */
(ub4)OCI_DEFAULT) /* mode */
) < 0)
return (-1);
/*定义第三个字段ADDR的输出变量 */
if (check_oci_error(errhp,
OCIDefineByPos((OCIStmt *)smthp,
(OCIDefine **)&defp,
errhp,
(ub4)3, /* position */
(void *)addr, /* valuep */
(sb4)200, /* value_sz */
(ub2)SQLT_STR, /* dty */
(void *)&ind_addr, /* indp */
(ub2 *)&alen_addr, /* alenp */
(ub2 *)&rcode_addr, /* column return code pointer */
(ub4)OCI_DEFAULT) /* mode */
) < 0)
return (-1);
/* 执行OCI语句,注意在查询语句执行时,iters要设置为0 */
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_NO_DATA)
break;
if (ind_id == -1)
sprintf(id_str, "NULL");
else
sprintf(id_str, "%d", id);
if (ind_name == -1)
sprintf(name, "NULL");
if (ind_addr == -1)
sprintf(addr, "NULL");
fprintf(stdout, "ID=%s, NAME=%s, ADDR=%s\n", id_str, name, addr);
}
return (0);
}
如果查询语句中有WHERE条件,那么条件字段会用占位符表示,通过绑定函数来关联占位符和条件变量值。比如查询ID=1的数据,那么OCI程序中的语句文本为SELECT ID, NAME, ADDR FROM test_tab WHERE ID=:1。占位符:1通过OCIBindByPos()函数来绑定数值。