OCI学习

1.OCIBindByName和OCIBindByPos

OCI提供了两种方法来绑定参数到SQL语句中的占位符:OCIBindByPos和OCIBindByName。

1.OCIBindByName函数原型:

OCIBindByName(
     OCIStmt *stmtp,
     OCIBind **bindpp,
     OCIError *errhp,
     const text *placeholder,
     sb4 placeh_len,
     dvoid *valuep,
     sb4 value_sz,
     ub2 dty,
     dvoid *indp,
     ub2 *alenp,
     ub2 *rcodep,
     ub4 maxarr_len,
     ub4 *curelep,
     ub4 mode
)

   - 通过占位符的名称绑定参数到SQL语句中的占位符位置。
   - 占位符的名称由参数"placeholder"指定。
   - 参数"placeh_len"指定占位符的名称长度。
   - 其他参数的含义:
     - valuep: 指向数据的指针。
     - value_sz: 数据的大小。
     - dty: 数据的类型。
     - indp: 指示数据的指针,用于处理空值或者处理绑定变量为数组时的偏移量。
     - alenp: 数据的实际长度。
     - rcodep: 返回代码的指针。
     - maxarr_len: 绑定变量为数组时,表示数组的最大长度。
     - curelep: 绑定变量为数组时,表示已填充的数组元素个数。
     - mode: 绑定模式。

 2.OCIBindByPos函数原型:

OCIBindByPos(
     OCIStmt *stmtp,
     OCIBind **bindpp,
     OCIError *errhp,
     ub4 position,
     dvoid *valuep,
     sb4 value_sz,
     ub2 dty,
     dvoid *indp,
     ub2 *alenp,
     ub2 *rcodep,
     ub4 maxarr_len,
     ub4 *curelep,
     ub4 mode
)

   - 通过占位符的位置绑定参数到SQL语句中的占位符位置。
   - 参数"position"指定了占位符的位置,从1开始计数。
   - 其他参数的含义与OCIBindByName类似。

这两个函数的作用是将应用程序中的变量或者数据与SQL语句中的占位符相关联。OCIBindByName通过占位符的名称进行绑定,而OCIBindByPos通过占位符的位置进行绑定。这两种方法可以根据具体的需求来选择使用。

3.OCIBindByName 示例:

OCIStmt *stmt;
OCIBind *bind;
int id = 100;

// 准备语句
OCIStmtPrepare(stmt, err, (text *)"SELECT name FROM employees
 WHERE emp_id = :empid", -1, OCI_NTV_SYNTAX, OCI_DEFAULT);

// 通过名称绑定变量
OCIBindByName(stmt, &bind, err, (text *)":empid", -1, &id,
 sizeof(int), SQLT_INT, NULL, NULL, NULL, 0, NULL, OCI_DEFAULT);

// 执行语句
OCIStmtExecute(svchp, stmt, err, 1, 0, NULL, NULL, OCI_DEFAULT);

// 获取结果
char name[50];
OCIStmtFetch2(stmt, err, 1, OCI_FETCH_NEXT, 0, OCI_DEFAULT);

// 从绑定变量中取值
OCIString *result;
OCIAttrGet(bind, OCI_HTYPE_BIND, &result, NULL, OCI_ATTR_VALUE, err);
printf("Name: %s\n", OCIStringPtr(result));

说明:

  • 以上示例通过名称绑定了一个变量:empid,并将其值设置为100。
  • 语句准备阶段,使用了一个带有参数的SELECT语句,其中的:empid就是绑定的变量。
  • 在执行语句后,通过OCIStmtFetch2函数获取结果集的下一行。
  • 使用OCIAttrGet函数从绑定变量中获取值,并以字符串形式打印输出。

4.OCIBindByPos 示例:

OCIStmt *stmt;
OCIBind *bind;
int id = 100;

// 准备语句
OCIStmtPrepare(stmt, err, (text *)"SELECT name FROM employees
 WHERE emp_id = ?", -1, OCI_NTV_SYNTAX, OCI_DEFAULT);

// 通过位置绑定变量
OCIBindByPos(stmt, &bind, err, 1, &id, sizeof(int), SQLT_INT,
 NULL, NULL, NULL, 0, NULL, OCI_DEFAULT);

// 执行语句
OCIStmtExecute(svchp, stmt, err, 1, 0, NULL, NULL, OCI_DEFAULT);

// 获取结果
char name[50];
OCIStmtFetch2(stmt, err, 1, OCI_FETCH_NEXT, 0, OCI_DEFAULT);

// 从绑定变量中取值
OCIString *result;
OCIAttrGet(bind, OCI_HTYPE_BIND, &result, NULL, OCI_ATTR_VALUE, err);
printf("Name: %s\n", OCIStringPtr(result));

说明:

  • 以上示例通过位置绑定了一个变量,将其值设置为100。
  • 语句准备阶段,使用了一个带有参数的SELECT语句,其中的?表示绑定变量的位置。
  • 在执行语句后,通过OCIStmtFetch2函数获取结果集的下一行。
  • 使用OCIAttrGet函数从绑定变量中获取值,并以字符串形式打印输出。

Note:

1.无论使用OCIBindByName还是OCIBindByPos,结果都是一样的。关键区别在于绑定变量的方式:OCIBindByName是通过名称绑定变量,而OCIBindByPos是通过位置绑定变量。

2.冒号后+名字和问号(:empid  或者  ?)都可以表示占位符。

2.OCI连接Oracle数据库的流程

#include <stdio.h>
#include <oci.h>

void check_error(OCIError *err, sword status) {
    text error_msg[512];
    sb4 error_code;
    
    if (status != OCI_SUCCESS) {
        OCIErrorGet(err, 1, NULL, &error_code, error_msg, sizeof(error_msg), OCI_HTYPE_ERROR);
        printf("Error: %d - %s\n", error_code, error_msg);
        exit(1);
    }
}

int main() {
    OCIEnv *env;
    OCIError *err;
    OCIServer *srv;
    OCISession *ses;
    OCISvcCtx *svc;
    sword status;
    
    // 初始化OCI环境
    status = OCIEnvCreate(&env, OCI_THREADED | OCI_OBJECT, NULL, NULL, NULL, NULL, 0, NULL);
    check_error(err, status);
    
    // 分配错误句柄
    status = OCIHandleAlloc(env, (dvoid **)&err, OCI_HTYPE_ERROR, 0, NULL);
    check_error(err, status);
    
    // 初始化服务器句柄
    status = OCIHandleAlloc(env, (dvoid **)&srv, OCI_HTYPE_SERVER, 0, NULL);
    check_error(err, status);
    
    // 初始化会话句柄
    status = OCIHandleAlloc(env, (dvoid **)&ses, OCI_HTYPE_SESSION, 0, NULL);
    check_error(err, status);
    
    // 创建服务器上下文
    status = OCIServerAttach(srv, err, (text *)"<db_name>", strlen("<db_name>"), OCI_DEFAULT);
    check_error(err, status);
    
    // 设置会话句柄的服务器属性
    status = OCIAttrSet(ses, OCI_HTYPE_SESSION, srv, 0, OCI_ATTR_SERVER, err);
    check_error(err, status);
    
    // 设置会话句柄的用户名和密码属性
    status = OCIAttrSet(ses, OCI_HTYPE_SESSION, (text *)"<username>", strlen("<username>"), OCI_ATTR_USERNAME, err);
    check_error(err, status);
    status = OCIAttrSet(ses, OCI_HTYPE_SESSION, (text *)"<password>", strlen("<password>"), OCI_ATTR_PASSWORD, err);
    check_error(err, status);
    
    // 创建服务器上下文句柄
    status = OCIHandleAlloc(env, (dvoid **)&svc, OCI_HTYPE_SVCCTX, 0, NULL);
    check_error(err, status);
    
    // 设置服务器上下文句柄的会话属性
    status = OCIAttrSet(svc, OCI_HTYPE_SVCCTX, ses, 0, OCI_ATTR_SESSION, err);
    check_error(err, status);
    
    // 开始会话
    status = OCISessionBegin(svc, err, ses, OCI_CRED_RDBMS, OCI_DEFAULT);
    check_error(err, status);
    
    printf("Connected to Oracle database\n");
    
    // 关闭会话
    status = OCISessionEnd(svc, err, ses, OCI_DEFAULT);
    check_error(err, status);
    
    // 断开服务器连接
    status = OCIServerDetach(srv, err, OCI_DEFAULT);
    check_error(err, status);
    
    // 释放句柄和环境
    OCIHandleFree(svc, OCI_HTYPE_SVCCTX);
    OCIHandleFree(ses, OCI_HTYPE_SESSION);
    OCIHandleFree(srv, OCI_HTYPE_SERVER);
    OCIHandleFree(err, OCI_HTYPE_ERROR);
    OCIHandleFree(env, OCI_HTYPE_ENV);
    
    return 0;
}

3.指示器变量

        指示器变量是用来处理数据库 NULL 值的变量。当执行 SELECT 或者 FETCH 语句时,如果不使用指示器变量并且列返回的值为 NULL 时,会显示错误信息。指示器变量必须采用 short 类型定义,并且指示器变量必须跟在宿主变量后面。

指示器变量的语法如下所示:

:host_variable [INDICATOR] :indicator_variable

在使用指示器变量后,可以检测出返回的列是否为 NULL:

  • 当指示器变量返回 -1 时,表示数据库返回 NULL 值。

  • 当指示器变量返回 0 时,表示列值被赋给了输出宿主变量。

  • 当指示器变量返回的值大于 0 时,表示将被截断列值付给了输出宿主变量,并且指示器变量存放着数据库列值的实际长度。

  • 当指示器变量返回值为 -2 时,表示被截断列值付给了输出宿主变量,但是实际长度不能确定。

指示器变量-OceanBase 嵌入式 SQL 预编译器-OceanBase文档中心-分布式数据库使用文档

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值