OCI(Oracle Call Interface)是Oracle提供的一个强大的C语言API,它能够让我们轻松地访问Oracle数据库,进行数据的增删改查等操作。OCI使用起来虽然不如PL/SQL那样简单,但是却能够提供更为灵活的操作,能够满足更多特定场景下的需求。下面,我们来看看OCI如何访问Oracle数据库。
首先,我们需要一个OCI环境句柄(OCIEnv*),然后创建一个OCI错误句柄(OCIError*),这个错误句柄将会用于记录操作过程中的错误信息。接着,我们需要连接到Oracle数据库,需要使用OCI的连接句柄(OCISvcCtx*)和OCI会话句柄(OCISession*)来实现连接操作。下面是示例代码:
OCIEnv* envhp; OCIError* errhp; OCISvcCtx* svchp; OCISession* usrhp; text* dbname = (text*) "ORCL"; text* username = (text*) "username"; text* password = (text*) "password"; ub4 dbname_len = strlen((char*) dbname); ub4 username_len = strlen((char*) username); ub4 password_len = strlen((char*) password); if (OCIEnvCreate(&envhp, OCI_THREADED, NULL, NULL, NULL,NULL,0,NULL)) { printf("OCIEnvCreate failed\n"); return -1; } if (OCIHandleAlloc(envhp, (dvoid**)&errhp, OCI_HTYPE_ERROR, 0, NULL)) { printf("OCIHandleAlloc OCI_HTYPE_ERROR failed\n"); return -1; } if (OCIHandleAlloc(envhp, (dvoid**)&svchp, OCI_HTYPE_SVCCTX, 0, NULL)) { printf("OCIHandleAlloc OCI_HTYPE_SVCCTX failed\n"); return -1; } if (OCIHandleAlloc(envhp, (dvoid**)&usrhp, OCI_HTYPE_SESSION, 0, NULL)) { printf("OCIHandleAlloc OCI_HTYPE_SESSION failed\n"); return -1; } if (OCILogon2(envhp, errhp, &svchp, (const OraText*) dbname, dbname_len, (const OraText*) username, username_len, (const OraText*) password, password_len, OCI_DEFAULT)) { printf("OCILogon2 failed\n"); return -1; }
通过上面的代码,我们就成功地连接到了Oracle数据库。接下来,我们可以通过OCI的语句句柄(OCIStmt*)来执行SQL语句。例如,我们可以查询一个名为“t_user”的数据表中的所有数据,如下:
OCIStmt* stmthp; text* sql = (text*) "SELECT * FROM t_user"; ub4 sql_len = strlen((char*) sql); if (OCIHandleAlloc(envhp, (dvoid**)&stmthp, OCI_HTYPE_STMT, 0, NULL)) { printf("OCIHandleAlloc OCI_HTYPE_STMT failed\n"); return -1; } if (OCIStmtPrepare(stmthp, errhp, (const OraText*) sql, sql_len, OCI_NTV_SYNTAX, OCI_DEFAULT)) { printf("OCIStmtPrepare failed\n"); return -1; } if (OCIStmtExecute(svchp, stmthp, errhp, 0, 0, NULL, NULL, OCI_DEFAULT)) { printf("OCIStmtExecute failed\n"); return -1; } OCIParam* colparam; ub1 coltype; sb2 colname[30]; ub2 colname_len; ub2 colnamelen; ub4 i = 1; while (!OCIStmtFetch(stmthp, errhp, 1, OCI_FETCH_NEXT, OCI_DEFAULT)) { if (OCIParamGet(stmthp, OCI_HTYPE_STMT, errhp, (dvoid**)&colparam, i)) { printf("OCIParamGet failed\n"); return -1; } if (OCIAttrGet(colparam, OCI_DTYPE_PARAM, &(dvoid*)colname, &(ub4)colnamelen, OCI_ATTR_NAME, errhp)) { printf("OCIAttrGet OCI_ATTR_NAME failed\n"); return -1; } colname_len = colnamelen / sizeof(sb2); colname[colname_len] = 0; if (OCIAttrGet(colparam, OCI_DTYPE_PARAM, &coltype, 0, OCI_ATTR_DATA_TYPE, errhp)) { printf("OCIAttrGet OCI_ATTR_DATA_TYPE failed\n"); return -1; } if (coltype == SQLT_STR) { text strbuf[100]; ub2 strbuf_len; if (OCIAttrGet(colparam, OCI_DTYPE_PARAM, &strbuf, &strbuf_len, OCI_ATTR_DATA_SIZE, errhp)) { printf("OCIAttrGet OCI_ATTR_DATA_SIZE failed\n"); return -1; } if (OCIAttrGet(colparam, OCI_DTYPE_PARAM, &strbuf, &strbuf_len, OCI_ATTR_DATA, errhp)) { printf("OCIAttrGet OCI_ATTR_DATA failed\n"); return -1; } printf("%s\n", strbuf); } i++; }
上面的代码中,我们先通过OCIStmtPrepare方法准备好了一个SELECT语句,然后通过OCIStmtExecute方法执行这个语句,获取到了查询结果集。接着,我们通过OCIParamGet方法获取到每个字段,通过OCIAttrGet方法获取字段的名称和类型,并使用if语句判断该字段的类型是否为字符串类型。如果是字符串类型,则通过OCIAttrGet方法获取到该字段的值并输出。
总之,OCI是一个非常强大的API,它提供了大量的函数和方法,能够满足各种不同场景下的需求。在使用OCI时,应该注意灵活运用各种方法,并根据具体情况进行调整和优化。