OCI编程基础篇(九) 查询数据

查询数据是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()函数来绑定数值。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值