本文提供 C 应用程序连接 OceanBase 数据库的连接代码示例。
确保设置了基本的数据库开发环境。
确保满足如下硬件环境:
硬件平台:x86_64。
操作系统:CentOS/Redhat 系 Linux 发行版 7.2。
编译器:GCC 4.8。
请联系技术支持人员获取 OBCI 和 libobclient 的 RPM 安装包。
当您获取 RPM 包后,在命令行工具中以 root 用户权限执行如下命令进行 OBCI 驱动的安装:
rpm -ivh obci-<version>.x86_64.rpm rpm -ivh libobclient-<version>.x86_64.rpm
在默认情况下,软件包中包含的程序与文件将安装在如下路径中:
头文件被安装在
/u01/obclient/include 路径下。
库文件被安装在
/u01/obclient/lib 路径下。
本文通过具体实例介绍在 OceanBase 数据库 Oracle 模式下,C 应用程序通过 OBCI 与数据库服务器 OBServer 交互的基本方式。
初始化 OBCI 环境和线程。
/*初始化 OBCI 程序环境*/ OCIInitialize(OCI_DEFAULT, NULL, NULL, NULL, NULL) /*初始化环境句柄*/ OCIEnvInit(&envhp, OCI_DEFAULT, 0, 0)
分配必要的句柄与数据结构。
/*分配句柄*/ OCIHandleAlloc(envhp, (dvoid **)&svchp, OCI_HTYPE_SVCCTX, 0, 0) /*服务器环境句柄*/ OCIHandleAlloc(envhp, (dvoid **)&srvhp, OCI_HTYPE_SERVER, 0, 0) /*服务器句柄*/ OCIHandleAlloc(envhp, (dvoid **)&authp, OCI_HTYPE_SESSION, 0, 0) /*会话句柄*/ OCIHandleAlloc(envhp, (dvoid **)&errhp, OCI_HTYPE_ERROR, 0, 0) /*错误句柄*/ OCIHandleAlloc(envhp, (dvoid **)&dschp, OCI_HTYPE_DESCRIBE, 0, 0)
建立与数据库的连接以及创建用户会话。
/*设置用户名和密码*/ OCIAttrSet(authp, OCI_HTYPE_SESSION, (text *)strUserName, (ub4)strlen(strUserName), OCI_ATTR_USERNAME, errhp) OCIAttrSet(authp, OCI_HTYPE_SESSION, (text *)strPassword, (ub4)strlen(strPassword), OCI_ATTR_PASSWORD, errhp) /*设置服务器环境句柄属性*/ OCIAttrSet((dvoid *)svchp, (ub4)OCI_HTYPE_SVCCTX,(dvoid *)srvhp, (ub4)0, OCI_ATTR_SERVER, errhp) OCIAttrSet(svchp, OCI_HTYPE_SVCCTX, (dvoid *)authp,0, OCI_ATTR_SESSION, errhp) /*创建并开始一个用户会话*/ OCISessionBegin(svchp, errhp, authp, OCI_CRED_RDBMS, OCI_DEFAULT) OCIHandleAlloc(envhp, (dvoid **)&stmthp, OCI_HTYPE_STMT, 0, 0)
通过 SQL 与 OceanBase 服务器交换数据,而后再做数据处理。一条 SQL 语句在 OBCI 应用程序中的执行步骤如下:
通过调用函数
OCIStmtPrepare() 或者
OCIStmtPrepare2() 准备 SQL 语句。
OCIStmtPrepare(stmthp, errhp, (text *)sql, strlen(sql), OCI_NTV_SYNTAX,OCI_DEFAULT)
通过调用一个或者多个函数,如
OCIBindByPos() 或
OCIBindByName() 等把输入变量的地址绑定在 DML 语句中的占位符中。
OCIBindByPos(stmthp, &bidhp[0], errhp, 1, &szpersonid, sizeof(szpersonid), SQLT_INT, NULL, NULL, NULL, 0, NULL, 0) OCIBindByName(stmthp, &bidhp[0], errhp, (const OraText*)":personid", 9, &szpersonid, sizeof(szpersonid), SQLT_INT, NULL, NULL, NULL, 0, NULL, 0)
调用
OCIStmrExecute() 函数执行 SQL 语句。
OCIStmtExecute(svchp, stmthp, errhp, (ub4)1, (ub4)0, (CONST OCISnapshot *)0, (OCISnapshot *)0, (ub4)OCI_DEFAULT)
调用
OCIDefineByPos() 函数为 SQL 语句中的数据输出项定义输出变量。
OCIDefineByPos(stmthp, &defhp[0], errhp, 1, &szpersonid, sizeof(szpersonid), SQLT_INT, &ind[0], 0, 0, OCI_DEFAULT)
调用
OCIStmtFetch() 函数来获取查询的结果集。
OCIStmtFetch(stmthp, errhp, 1, OCI_FETCH_NEXT, OCI_DEFAULT)
结束用户会话与断开与数据库的连接。
/*结束会话*/ OCISessionEnd(svchp, errhp, authp, (ub4)0) /*断开与数据库的连接*/ OCIServerDetach(srvhp, errhp, OCI_DEFAULT)
释放在程序中所分配的句柄。
OCIHandleFree((dvoid *)dschp, OCI_HTYPE_DESCRIBE) OCIHandleFree((dvoid *)stmthp, OCI_HTYPE_STMT) OCIHandleFree((dvoid *)errhp, OCI_HTYPE_ERROR) OCIHandleFree((dvoid *)authp, OCI_HTYPE_SESSION) OCIHandleFree((dvoid *)svchp, OCI_HTYPE_SVCCTX) OCIHandleFree((dvoid *)srvhp, OCI_HTYPE_SERVER)
示例文件
test.c 代码内容如下
/**********************************************************
* Copyright(C) 2014 - 2020 Alibaba Inc. All Rights Reserved.
*
* Filename: ob_oci_test.c
* Description: ----
* Create: 2020-07-07 10:14:59
* Last Modified: 2020-07-07 10:14:59
***********************************************************/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <malloc.h>
#include "oci.h"
/*声明句柄*/
OCIEnv *envhp; /*环境句柄*/
OCISvcCtx *svchp; /*服务环境句柄*/
OCIServer *srvhp; /*服务器句柄*/
OCISession *authp; /*会话句柄*/
OCIStmt *stmthp; /*语句句柄*/
OCIDescribe *dschp; /*描述句柄*/
OCIError *errhp; /*错误句柄*/
OCIDefine *defhp[3]; /*定义句柄*/
OCIBind *bidhp[4]; /*绑定句柄*/
sb2 ind[3]; /*指示符变量*/
/*绑定select结果集的参数*/
text szpersonid[9]; /*存储personid列*/
text szsex[2]; /*存储sex列*/
text szname[51]; /*存储name列*/
text szemail[51]; /*存储mail列*/
text szphone[26]; /*存储phone列*/
char sql[256]; /*存储执行的sql语句*/
int main(int argc, char *argv[])
{
char strServerName[50];
char strUserName[50];
char strPassword[50];
/*设置服务器,用户名和密码*/
strcpy(strServerName, "172.30.xx.xx:2881");
strcpy(strUserName, "s**@oracle");
strcpy(strPassword, "***1**");
/*初始化OCI应用环境*/
OCIInitialize(OCI_DEFAULT, NULL, NULL, NULL, NULL);
/*初始化环境句柄*/
OCIEnvInit(&envhp, OCI_DEFAULT, 0, 0);
/*分配句柄*/
OCIHandleAlloc(envhp, (dvoid **)&svchp, OCI_HTYPE_SVCCTX, 0, 0);
/*服务器环境句柄*/
OCIHandleAlloc(envhp, (dvoid **)&srvhp, OCI_HTYPE_SERVER, 0, 0);
/*服务器句柄*/
OCIHandleAlloc(envhp, (dvoid **)&authp, OCI_HTYPE_SESSION, 0, 0);
/*会话句柄*/
OCIHandleAlloc(envhp, (dvoid **)&errhp, OCI_HTYPE_ERROR, 0, 0);
/*错误句柄*/
OCIHandleAlloc(envhp, (dvoid **)&dschp, OCI_HTYPE_DESCRIBE, 0, 0);
/*描述符句柄*/
/*连接服务器*/
OCIServerAttach(srvhp, errhp, (text *)strServerName,
(sb4)strlen(strServerName), OCI_DEFAULT);
/*设置用户名和密码*/
OCIAttrSet(authp, OCI_HTYPE_SESSION, (text *)strUserName,
(ub4)strlen(strUserName), OCI_ATTR_USERNAME, errhp);
OCIAttrSet(authp, OCI_HTYPE_SESSION, (text *)strPassword,
(ub4)strlen(strPassword), OCI_ATTR_PASSWORD, errhp);
/*设置服务器环境句柄属性*/
OCIAttrSet((dvoid *)svchp, (ub4)OCI_HTYPE_SVCCTX,
(dvoid *)srvhp, (ub4)0, OCI_ATTR_SERVER, errhp);
OCIAttrSet(svchp, OCI_HTYPE_SVCCTX, (dvoid *)authp,
0, OCI_ATTR_SESSION, errhp);
/*创建并开始一个用户会话*/
OCISessionBegin(svchp, errhp, authp, OCI_CRED_RDBMS, OCI_DEFAULT);
OCIHandleAlloc(envhp, (dvoid **)&stmthp, OCI_HTYPE_STMT, 0, 0);
/*语句句柄*/
/************************************************************************/
/*查询person表*/
/************************************************************************/
strcpy(sql, "select personid ,name,phone from person;");
/*准备SQL语句*/
OCIStmtPrepare(stmthp, errhp, (text *)sql, strlen(sql), OCI_NTV_SYNTAX, OCI_DEFAULT);
/*绑定输出列*/
OCIDefineByPos(stmthp, &defhp[0], errhp, 1, (ub1 *)szpersonid,
sizeof(szpersonid), SQLT_STR, &ind[0], 0, 0, OCI_DEFAULT);
OCIDefineByPos(stmthp, &defhp[1], errhp, 2, (ub1 *)szname,
sizeof(szname), SQLT_STR, &ind[1], 0, 0, OCI_DEFAULT);
OCIDefineByPos(stmthp, &defhp[2], errhp, 3, (ub1 *)szphone,
sizeof(szphone), SQLT_STR, &ind[2], 0, 0, OCI_DEFAULT);
/*执行SQL语句*/
OCIStmtExecute(svchp, stmthp, errhp, (ub4)0, 0, NULL, NULL,
OCI_DEFAULT);
printf("%-10s%-10s%-10s\n", "PERSONID", "NAME", "PHONE");
while ((OCIStmtFetch(stmthp,
errhp, 1, OCI_FETCH_NEXT, OCI_DEFAULT)) != OCI_NO_DATA)
{
printf("%-10s", szpersonid);
printf("%-10s", szname);
printf("%-10s\n", szphone);
}
/*提交到数据库*/
OCITransCommit(svchp, errhp, OCI_DEFAULT);
//结束会话
OCISessionEnd(svchp, errhp, authp, (ub4)0);
//断开与数据库的连接
OCIServerDetach(srvhp, errhp, OCI_DEFAULT);
//释放OCI句柄
OCIHandleFree((dvoid *)dschp, OCI_HTYPE_DESCRIBE);
OCIHandleFree((dvoid *)stmthp, OCI_HTYPE_STMT);
OCIHandleFree((dvoid *)errhp, OCI_HTYPE_ERROR);
OCIHandleFree((dvoid *)authp, OCI_HTYPE_SESSION);
OCIHandleFree((dvoid *)svchp, OCI_HTYPE_SVCCTX);
OCIHandleFree((dvoid *)srvhp, OCI_HTYPE_SERVER);
return 0;
}
代码中以下数据库连接信息需要根据实际情况填写:
strServerName:
ip:port。OceanBase 数据库连接 IP,通常是一个 OBProxy 地址,以及访问所用的端口号。
strUserName:
用户名@租户名。租户的连接用户,oracle 模式的管理员用户名默认是
sys。
说明
对于专有云或独立部署的场景,
username的格式为:String username= "用户名@租户#集群"。
strPassword:用户密码。
代码编辑完成后,可以通过如下命令进行编译和执行,正确返回查询结果说明数据库连接成功:
//编译 gcc test.c -I/u01/obclient/include /u01/obclient/lib/libobci.a -L/usr/local/lib64 -lstdc++ -lpthread -ldl -lm -g -o test //运行 ./test
关于 OBCI 的详细安装和使用信息,请参考官网文档 《 OceanBase C 语言调用接口》。
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/70026124/viewspace-2932839/ ,如需转载,请注明出处,否则将追究法律责任。