1. 简介
Oracle是目前世界上最大的数据库管理系统之一,使用广泛,而C语言作为一种中级编程语言,也具有一定的使用率。在C语言的开发过程中,经常需要调用Oracle数据库的存储过程来实现一些功能,本文将介绍如何使用C语言调用Oracle数据库的存储过程。
2. 准备工作
2.1. 安装Oracle客户端
在使用C语言调用Oracle数据库的存储过程之前,需要先安装Oracle客户端。Oracle客户端安装包包含了连接Oracle数据库所需的驱动程序和可执行文件。请按照您的操作系统版本选择相应的Oracle客户端版本进行安装。
2.2. 配置环境变量
安装完Oracle客户端之后,还需要配置环境变量,将Oracle客户端的可执行文件路径添加到系统的PATH环境变量中。这样,当我们在C程序中调用Oracle客户端的可执行文件时,系统就可以自动找到相应的文件。
3. C语言调用Oracle存储过程
3.1. 连接Oracle数据库
在C语言中,我们可以使用Oracle提供的OCILibrary来实现与Oracle数据库的连接。以下是连接Oracle数据库的代码实例:
#include <stdio.h>
#include <stdlib.h>
#include <oci.h> //OCILibrary头文件
void checkerr(OCIError *errhp, sword status)
{
text errbuf[512];
sb4 errcode = 0;
switch (status)
{
case OCI_SUCCESS:
break;
case OCI_SUCCESS_WITH_INFO:
printf("Error - OCI_SUCCESS_WITH_INFO\n");
break;
case OCI_NEED_DATA:
printf("Error - OCI_NEED_DATA\n");
break;
case OCI_NO_DATA:
printf("Error - OCI_NO_DATA\n");
break;
case OCI_ERROR:
OCIErrorGet((dvoid *) errhp, (ub4) 1, (text *) NULL, &errcode, errbuf, (ub4) sizeof(errbuf), OCI_HTYPE_ERROR);
printf("Error - %.*s\n", 512, errbuf);
break;
case OCI_INVALID_HANDLE:
printf("Error - OCI_INVALID_HANDLE\n");
break;
case OCI_STILL_EXECUTING:
printf("Error - OCI_STILL_EXECUTING\n");
break;
case OCI_CONTINUE:
printf("Error - OCI_CONTINUE\n");
break;
default:
break;
}
}
int main()
{
OCIEnv *envhp; //OCI环境句柄
OCIError *errhp; //OCI错误句柄
OCIServer *srvhp; //OCI Server句柄
OCISvcCtx *svchp; //OCI Service Context句柄
OCIStmt *stmthp; //OCI语句句柄
OCIDefine *defhp; //OCI取值句柄
OCIBind *bindhp; //OCI绑定变量句柄
OCISession *authp; //OCI会话句柄
int status;
//1. 初始化OCI环境句柄和错误句柄
status = OCIEnvCreate(&envhp, OCI_THREADED | OCI_OBJECT, (dvoid *) 0, (dvoid * (*)(dvoid *, size_t)) 0, (dvoid * (*)(dvoid *, dvoid *, size_t)) 0, (void (*)(dvoid *, dvoid *)) 0, 0, (dvoid **) 0);
checkerr(0, status);
status = OCIHandleAlloc((dvoid *) envhp, (dvoid **) &errhp, OCI_HTYPE_ERROR, 0, (dvoid **) 0);
checkerr(errhp, status);
//2. 初始化OCI Server、OCI Service Context、OCI语句句柄
status = OCIHandleAlloc((dvoid *) envhp, (dvoid **) &srvhp, OCI_HTYPE_SERVER, 0, (dvoid **) 0);
checkerr(errhp, status);
status = OCIHandleAlloc((dvoid *) envhp, (dvoid **) &svchp, OCI_HTYPE_SVCCTX, 0, (dvoid **) 0);
checkerr(errhp, status);
status = OCIHandleAlloc((dvoid *) envhp, (dvoid **) &stmthp, OCI_HTYPE_STMT, 0, (dvoid **) 0);
checkerr(errhp, status);
//3. 连接到Oracle数据库
status = OCILogon(envhp, errhp, &svchp, (OraText *) "username", (ub4) strlen("username"), (OraText *) "password", (ub4) strlen("password"), (OraText *) "dbname", (ub4) strlen("dbname"));
checkerr(errhp, status);
}
在以上代码中,我们通过OCIEnvCreate函数创建了OCI环境句柄和错误句柄,然后使用OCIHandleAlloc分配了OCI Server、OCI Service Context和OCI语句句柄。最后,使用OCILogon函数连接到Oracle数据库。
需要注意的是,在使用OCILogon函数连接Oracle数据库时,需要提供数据库的用户名、密码和数据库名。
3.2. 准备调用存储过程的SQL语句
在C语言中调用Oracle存储过程,需要先准备好调用存储过程的SQL语句。以下是调用存储过程的SQL语句的示例:
begin
procedure_name(:param1, :param2, :out_param);
end;
在以上SQL语句中,procedure_name为存储过程的名称,:param1、:param2为输入参数,:out_param为输出参数。在C程序中,我们可以使用OCIBind函数将需要传递给存储过程的参数进行绑定,使用OCIDefine函数将存储过程返回的结果取出。
3.3. 调用存储过程
以下是使用C语言调用Oracle存储过程的示例代码:
#include <stdio.h>
#include <stdlib.h>
#include <oci.h> //OCILibrary头文件
void checkerr(OCIError *errhp, sword status)
{
text errbuf[512];
sb4 errcode = 0;
switch (status)
{
case OCI_SUCCESS:
break;
case OCI_SUCCESS_WITH_INFO:
printf("Error - OCI_SUCCESS_WITH_INFO\n");
break;
case OCI_NEED_DATA:
printf("Error - OCI_NEED_DATA\n");
break;
case OCI_NO_DATA:
printf("Error - OCI_NO_DATA\n");
break;
case OCI_ERROR:
OCIErrorGet((dvoid *) errhp, (ub4) 1, (text *) NULL, &errcode, errbuf, (ub4) sizeof(errbuf), OCI_HTYPE_ERROR);
printf("Error - %.*s\n", 512, errbuf);
break;
case OCI_INVALID_HANDLE:
printf("Error - OCI_INVALID_HANDLE\n");
break;
case OCI_STILL_EXECUTING:
printf("Error - OCI_STILL_EXECUTING\n");
break;
case OCI_CONTINUE:
printf("Error - OCI_CONTINUE\n");
break;
default:
break;
}
}
int main()
{
OCIEnv *envhp; //OCI环境句柄
OCIError *errhp; //OCI错误句柄
OCIServer *srvhp; //OCI Server句柄
OCISvcCtx *svchp; //OCI Service Context句柄
OCIStmt *stmthp; //OCI语句句柄
OCIDefine *defhp; //OCI取值句柄
OCIBind *bindhp; //OCI绑定变量句柄
OCISession *authp; //OCI会话句柄
int status;
int param1 = 1;
char param2[16] = "param2";
int out_param;
//1. 初始化OCI环境句柄和错误句柄
status = OCIEnvCreate(&envhp, OCI_THREADED | OCI_OBJECT, (dvoid *) 0, (dvoid * (*)(dvoid *, size_t)) 0, (dvoid * (*)(dvoid *, dvoid *, size_t)) 0, (void (*)(dvoid *, dvoid *)) 0, 0, (dvoid **) 0);
checkerr(0, status);
status = OCIHandleAlloc((dvoid *) envhp, (dvoid **) &errhp, OCI_HTYPE_ERROR, 0, (dvoid **) 0);
checkerr(errhp, status);
//2. 初始化OCI Server、OCI Service Context、OCI语句句柄
status = OCIHandleAlloc((dvoid *) envhp, (dvoid **) &srvhp, OCI_HTYPE_SERVER, 0, (dvoid **) 0);
checkerr(errhp, status);
status = OCIHandleAlloc((dvoid *) envhp, (dvoid **) &svchp, OCI_HTYPE_SVCCTX, 0, (dvoid **) 0);
checkerr(errhp, status);
status = OCIHandleAlloc((dvoid *) envhp, (dvoid **) &stmthp, OCI_HTYPE_STMT, 0, (dvoid **) 0);
checkerr(errhp, status);
//3. 连接到Oracle数据库
status = OCILogon(envhp, errhp, &svchp, (OraText *) "username", (ub4) strlen("username"), (OraText *) "password", (ub4) strlen("password"), (OraText *) "dbname", (ub4) strlen("dbname"));
checkerr(errhp, status);
//4. 准备调用存储过程的SQL语句
const char *sql = "begin procedure_name(:param1, :param2, :out_param); end;";
OCIStmtPrepare(stmthp, errhp, (text *) sql, strlen(sql), OCI_NTV_SYNTAX, OCI_DEFAULT);
//5. 绑定输入参数
bindhp = NULL;
OCIBindByName(stmthp, &bindhp, errhp, (text *) ":param1", strlen(":param1"), ¶m1, sizeof(int), SQLT_INT, 0, 0, 0, 0, 0, OCI_DEFAULT);
bindhp = NULL;
OCIBindByName(stmthp, &bindhp, errhp, (text *) ":param2", strlen(":param2"), param2, sizeof(param2), SQLT_STR, 0, 0, 0, 0, 0, OCI_DEFAULT);
//6. 绑定输出参数
defhp = NULL;
OCIDefineByPos(stmthp, &defhp, errhp, 3, &out_param, sizeof(int), SQLT_INT, 0, 0, 0, OCI_DEFAULT);
//7. 执行SQL语句
OCIStmtExecute(svchp, stmthp, errhp, 1, 0, NULL, NULL, OCI_DEFAULT);
//8. 取出输出参数
printf("%d\n", out_param);
//9. 释放资源
status = OCILogoff(svchp, errhp);
checkerr(errhp, status);
status = OCIHandleFree((dvoid *) envhp, OCI_HTYPE_ENV);
checkerr(0, status);
return 0;
}
在以上代码中,我们先定义了需要传递给存储过程的参数。然后,初始化OCI环境句柄和错误句柄,并使用OCIHandleAlloc分配OCI Server、OCI Service Context和OCI语句句柄。接着,使用OCILogon函数连接到Oracle数据库。
在连接到Oracle数据库之后,我们准备了调用存储过程的SQL语句,并使用OCIBindByName函数将需要传递给存储过程的参数进行绑定。最后,使用OCIDefineByPos函数将存储过程返回的结果取出。
在所有操作执行完毕后,使用OCILogoff函数断开与Oracle数据库的连接,使用OCIHandleFree函数释放资源。
4. 总结
本文介绍了如何使用C语言调用Oracle数据库的存储过程。在C程序中,我们可以使用OCILibrary来实现与Oracle数据库的连接,使用OCIBind函数将需要传递给存储过程的参数进行绑定,使用OCIDefine函数将存储过程返回的结果取出。