---
title: "创建 C 示例应用程序 - OceanBase 数据库 V4.1.0 | OceanBase 文档中心"
description: 创建 C 示例应用程序 本文介绍 C 应用程序如何通过 OBCI 连接并使用 OceanBase 数据库。 功能适用性 该内容仅适用于 OceanBase 数据库企业版。OceanBase 数据库社区版仅提供 MySQL 模式。 前提条件 确保设置了基本的数据库开发环境。 确保满足如下硬件环境： 硬件平台：x86_6…
---
切换语言

- 中文站 - 简体中文
- International - English
- 日本站 - 日本語

文档反馈![](https://mdn.alipayobjects.com/huamei_22khvb/afts/img/A*P8CuR4UJ_FkAAAAAAAAAAAAADiGDAQ/original) OceanBase 数据库分布式版 - V 4.1.0

# 创建 C 示例应用程序

更新时间：2025-03-25 15:42:33

[编辑](https://github.com/oceanbase/oceanbase-doc/edit/V4.1.0/zh-CN/200.quickstart/300.create-sample-application-of-oracle-mode/300.c-application-of-oracle-model.md)  

本文介绍 C 应用程序如何通过 OBCI 连接并使用 OceanBase 数据库。

#### 功能适用性

该内容仅适用于 OceanBase 数据库企业版。OceanBase 数据库社区版仅提供 MySQL 模式。

## 前提条件

- 确保设置了基本的数据库开发环境。
 - 确保满足如下硬件环境：

     - 硬件平台：x86_64。
     - 操作系统：CentOS/Redhat 系 Linux 发行版 7.2。
     - 编译器：GCC 4.8。
 - 请联系技术支持人员获取 OBCI 和 LibOBClient 的 RPM 安装包。

#### 注意

前提条件还需注意以下事项：

- 从 OBCI V2.0.4 开始，RPM 包的 `include` 文件夹中不再包含 `oci.h`、`ociap.h` 等头文件，业务编译需要首先安装 Oracle clntsh 相关 RPM，直接使用其头文件。
 - OceanBase：V2.2.76 及以上版本（推荐使用 OceanBase 数据库 V4.0 及以上版本，以体验当前版本的完整功能）。
 - ODP（OBProxy）：推荐 V4.0 及以上版本。
 - libobclient：V2.1.1 及以上版本。
 - 安装 Oracle 相关驱动文件 `oracle-instantclient`（从 OBCI V2.0.4 开始需要依赖 Oracle 头文件）。
 - 已安装 OBCI，并已提前部署 GCC 编译器。

### 步骤一：获取数据库连接串

联系 OceanBase 数据库部署人员或者管理员获取相应的数据库连接串，例如：

```sql
obclient  -h100.88.xx.xx -usys@oracle -p****** -P2881

```

数据库连接串包含了访问数据库所需的参数信息，在创建应用程序前，可通过数据库连接串验证登录数据库，保证连接串参数信息正确。

参数说明：

- **-h**：OceanBase 数据库连接 IP，有时候是一个 ODP 地址。
 - **-u**：租户的连接用户名，格式为 **用户@租户#集群名称**，租户的连接用户，Oracle 模式的管理员用户名默认是 `sys`。直连数据库时不填集群名称，通过 ODP 连接时需要填写。
 - **-p**：用户密码。
 - **-P**：OceanBase 数据库连接端口，也是 ODP 的监听端口。

### 步骤二：安装 C 相关驱动

当您获取 RPM 包后，在命令行工具中以 root 用户权限执行如下命令进行 OBCI 驱动的安装：

```shell
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 节点交互的基本方式。

1. 初始化 OBCI 环境和线程。

   ```c
   /*初始化 OBCI 程序环境*/
   OCIInitialize(OCI_DEFAULT, NULL, NULL, NULL, NULL)

   /*初始化环境句柄*/
   OCIEnvInit(&envhp, OCI_DEFAULT, 0, 0)

   ```
 2. 分配必要的句柄与数据结构。

   ```c
   /*服务上下文句柄*/
   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)

   ```
 3. 建立与数据库的连接以及创建用户会话。

   ```c
   /*设置用户名和密码*/
    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)

   ```
 4. 通过 SQL 与 OceanBase 服务器交换数据，而后再做数据处理。一条 SQL 语句在 OBCI 应用程序中的执行步骤如下：

      1. 通过调用函数 `OCIStmtPrepare()` 或者 `OCIStmtPrepare2()` 准备 SQL 语句。

        ```c
        OCIStmtPrepare(stmthp, errhp, (text *)sql, strlen(sql), OCI_NTV_SYNTAX,OCI_DEFAULT)

        ```
      2. 通过调用一个或者多个函数，如 `OCIBindByPos()` 或 `OCIBindByName()` 等把输入变量的地址绑定在 DML 语句中的占位符中。

        ```c
        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)

        ```
      3. 调用 `OCIStmrExecute()` 函数执行 SQL 语句。

        ```c
        OCIStmtExecute(svchp, stmthp, errhp, (ub4)1, (ub4)0, (CONST OCISnapshot *)0,
        (OCISnapshot *)0, (ub4)OCI_DEFAULT)

        ```
      4. 调用 `OCIDefineByPos()` 函数为 SQL 语句中的数据输出项定义输出变量。

        ```c
        OCIDefineByPos(stmthp, &defhp[0], errhp, 1, &szpersonid,
        sizeof(szpersonid), SQLT_INT, &ind[0], 0, 0, OCI_DEFAULT)

        ```
      5. 调用 `OCIStmtFetch()` 函数来获取查询的结果集。

        ```c
        OCIStmtFetch(stmthp, errhp, 1, OCI_FETCH_NEXT, OCI_DEFAULT)

        ```
 5. 结束用户会话与断开与数据库的连接。

   ```c
   /*结束会话*/
     OCISessionEnd(svchp, errhp, authp, (ub4)0)

   /*断开与数据库的连接*/
     OCIServerDetach(srvhp, errhp, OCI_DEFAULT)

   ```
 6. 释放在程序中所分配的句柄。

   ```c
   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` 代码内容如下：

```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 结果集的参数*/
int szpersonid; /*存储 personid 列*/
text szname[51];    /*存储 name 列*/
text szemail[51];   /*存储 mail 列*/
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, "******");
  /*初始化 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 表*/
  /************************************************************************/
  static text* SQL_CREATE_TB = (text*)"create table person(personid number, name varchar(256), email  varchar(256))";
  /*准备 SQL 语句*/
  OCIStmtPrepare(stmthp, errhp, SQL_CREATE_TB, strlen((char *)SQL_CREATE_TB),OCI_NTV_SYNTAX, OCI_DEFAULT);
  /*执行 SQL 语句*/
  OCIStmtExecute(svchp, stmthp, errhp, 1, 0, 0, 0, OCI_DEFAULT);
  /*提交到数据库*/
  OCITransCommit(svchp, errhp, OCI_DEFAULT);

  /************************************************************************/
  /*插入数据*/
  /************************************************************************/
  memset(sql, 0, sizeof(sql));
  strcpy(sql, "insert into person values(:personid,:name,:email)");
  /*准备 SQL 语句*/
  OCIStmtPrepare(stmthp, errhp, (text *)sql, strlen(sql),OCI_NTV_SYNTAX, OCI_DEFAULT);
  /*绑定输入列*/
  OCIBindByName(stmthp, &bidhp[0], errhp, (const OraText*)":personid", 9, &szpersonid, sizeof(szpersonid), SQLT_INT, NULL, NULL, NULL, 0, NULL, 0);
  OCIBindByName(stmthp, &bidhp[2], errhp, (const OraText*)":name", 5, szname, sizeof(szname), SQLT_STR, NULL, NULL, NULL, 0, NULL, 0);
  OCIBindByName(stmthp, &bidhp[3], errhp, (const OraText*)":email", 6, szemail, sizeof(szemail), SQLT_STR, NULL, NULL, NULL, 0, NULL, 0);
  /*设置输入参数*/
  szpersonid = 1;
  memset(szname, 0, sizeof(szname));
  strcpy((char*)szname, "obtest");
  memset(szemail, 0, sizeof(szemail));
  strcpy((char*)szemail, "t@ob.com");
  /*执行 SQL 语句*/
  OCIStmtExecute(svchp, stmthp, errhp, (ub4)1, (ub4)0, (CONST OCISnapshot *)0, (OCISnapshot *)0, (ub4)OCI_DEFAULT);
  /*提交到数据库*/
  OCITransCommit(svchp, errhp, OCI_DEFAULT);

  /************************************************************************/
  /*查询 person 表*/
  /************************************************************************/
  strcpy(sql, "select personid ,name,email from person;");
  /*准备 SQL 语句*/
  OCIStmtPrepare(stmthp, errhp, (text *)sql, strlen(sql), OCI_NTV_SYNTAX, OCI_DEFAULT);
  /*绑定输出列*/
  OCIDefineByPos(stmthp, &defhp[0], errhp, 1, &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 *)szemail, sizeof(szemail), 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", "email");
  while ((OCIStmtFetch(stmthp, errhp, 1, OCI_FETCH_NEXT, OCI_DEFAULT)) != OCI_NO_DATA)
  {
    printf("%-10d", szpersonid);
    printf("%-10s", szname);
    printf("%-10s\n", szemail);
    break;
  }
  /*提交到数据库*/
  OCITransCommit(svchp, errhp, OCI_DEFAULT);

  /************************************************************************/
  /*删除 person 表*/
  /************************************************************************/
  static text* SQL_DROP_TB   = (text*)"drop table person";
  /*准备 SQL 语句*/
  OCIStmtPrepare(stmthp, errhp, (text*)SQL_DROP_TB, strlen((char *)SQL_DROP_TB), OCI_NTV_SYNTAX, OCI_DEFAULT);
  /*执行 SQL 语句*/
  OCIStmtExecute(svchp, stmthp, errhp, 1, 0, 0, 0, OCI_COMMIT_ON_SUCCESS);
  /*提交到数据库*/
  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;
}

```

修改代码中的数据库连接参数。参考如下字段，对应的值，则取自步骤一获取的数据库连接串。

```c
strcpy(strServerName, "172.30.xx.xx:2881");
strcpy(strUserName, "s**@oracle");
strcpy(strPassword, "******");

```

- **strServerName**：取自 `-h` 和 `-P` 参数，`IP:port`。OceanBase 数据库连接 IP，通常是一个 ODP 地址，以及访问所用的端口号。
 - **strUserName**： 取自 `-u` 参数，租户的连接用户名，格式为 **用户@租户#集群名称**，Oracle 模式的管理员用户名默认是 `sys`。直连数据库时不填集群名称，通过 ODP 连接时需要填写。
 - **strPassword**：取自 `-p` 参数，用户密码。

### 步骤四：执行应用程序

代码编辑完成后，可以通过如下命令进行编译：

```c
//编译
gcc test.c -I/u01/obclient/include /u01/obclient/lib/libobci.a -L/usr/local/lib64 -lstdc++ -lpthread -ldl -lm -g -o test

```

编译完成后，运行得到如下结果，说明数据库连接成功且语句执行正常：

```bash
./test

PERSONID  NAME      email
1         obtest    t@ob.com

```

## 更多信息

关于 OBCI 的详细安装和使用信息，请参考官网文档 《[OceanBase C 语言调用接口](https://www.oceanbase.com/docs/enterprise-obci-cn-100000000003805846)》。

 上一篇 下一篇 ![有帮助](https://gw.alipayobjects.com/mdn/ob_asset/afts/img/A*y6ocSqN8cqsAAAAAAAAAAAAAARQnAQ)![无帮助](https://gw.alipayobjects.com/mdn/ob_asset/afts/img/A*BG9IQJyLHF8AAAAAAAAAAAAAARQnAQ)![反馈](https://gw.alipayobjects.com/mdn/ob_asset/afts/img/A*eTWdQKCRKHwAAAAAAAAAAAAAARQnAQ)[AI](https://www.oceanbase.com/obi) 咨询热线
