OCI编程基础篇(九) 查询数据
访问www.tomcoding.com网站,学习Oracle内部数据结构,详细文档说明,下载Oracle的exp/imp,DUL,logminer,ASM工具的源代码,学习高技术含量的内容。
查询数据是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()函数来绑定数值。

浙公网安备 33010602011771号