---
title: "OceanBase Connector/ODBC 连接 OceanBase 数据库示例程序 - OceanBase 数据库 V4.5.0 | OceanBase 文档中心"
description: OceanBase Connector/ODBC 连接 OceanBase 数据库示例程序 本文将介绍如何使用 OceanBase Connector/ODBC 和 OceanBase 数据库构建一个应用程序，实现创建表、插入数据和查询数据等基本操作。 点击下载 c-oceanbase-odbc 示例工程 Ocean…
---
切换语言

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

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

# OceanBase Connector/ODBC 连接 OceanBase 数据库示例程序

更新时间：2026-03-21 19:15:15

[编辑](https://github.com/oceanbase/oceanbase-doc/edit/V4.5.0/zh-CN/300.develop/200.application-development-of-oracle-mode/200.sample-program-of-oracle-mode/300.c-of-oracle-mode/200.oceanbase-connector-odbc-connection-to-oceanbase-database-sample-program.md)  

本文将介绍如何使用 OceanBase Connector/ODBC 和 OceanBase 数据库构建一个应用程序，实现创建表、插入数据和查询数据等基本操作。

 [![](https://file.oceanbase.com/doc/img/lQLPJyFovGIOcJQWFrAqhLlgRRsPvwU-H7hJ_i0A_22_22.png) 点击下载 c-oceanbase-odbc 示例工程](https://obbusiness-private.oss-cn-shanghai.aliyuncs.com/doc/img/observer-enterprise/V4.2.0/3.develop/demo/C%26C%2B%2B/c-oceanbase-odbc.zip) [![](https://mdn.alipayobjects.com/huamei_22khvb/afts/img/A*DFPmToHK6hgAAAAAAAAAAAAADiGDAQ/original) OceanBase Connector/ODBC 连接 OceanBase 数据库示例程序（Oracle 模式）](https://obbusiness-private.oss-cn-shanghai.aliyuncs.com/video-center/video/video/07%20c-oceanbase-odbc.mp4)  

## 前提条件

- 您已安装 OceanBase 数据库并且创建 Oracle 模式的用户租户。安装 OceanBase 数据库的详细信息，请参见 [部署概述](https://www.oceanbase.com/docs/common-oceanbase-database-cn-1000000004475420)。
 - 您已安装 Visual Studio。
 - 您已安装 OceanBase Connector/ODBC 驱动程序。

  #### 说明

  请在 OceanBase 官方网站 [资源 > 下载中心 > 企业版](https://www.oceanbase.com/softwarecenter-enterprise) 页面下的 **驱动和中间件** 模块中下载 OceanBase ODBC 驱动程序 Windows 版本的安装包。Windows 版 OceanBase Connector/ODBC 驱动安装包为一键部署式，根据默认指导步骤安装即可。

## 操作步骤

#### 说明

本文中给出的操作步骤是在 Windows 环境下使用 Visual Studio Community 2019 编译和运行该项目的步骤。如果您使用的是其他操作系统环境或编译器，那么操作步骤可能会略有不同。

1. 打开 `c-oceanbase-odbc` 项目。
 2. 配置 `c-oceanbase-odbc` 项目属性。
 3. 获取 OceanBase 数据库连接信息。
 4. 修改 `c-oceanbase-odbc` 项目中的数据库连接信息。
 5. 构建项目。
 6. 运行应用程序。
 7. 查看输出结果。

### 步骤一：打开 c-oceanbase-odbc 项目

1. 启动 Visual Studio Community 2019。
 2. 打开现有项目。

      1. 在 Visual Studio Community 2019 的起始界面上，在开始使用下面点击 **打开项目或解决方案(P)** 按钮。或者在 Visual Studio Community 2019 的起始界面上，在开始使用下面点击 **继续但无需代码(W)** 按钮；在上面菜单栏中选择 **文件** -> **打开** -> **项目/解决方案(P)**。

        ![1](https://obbusiness-private.oss-cn-shanghai.aliyuncs.com/doc/img/observer-enterprise/V4.2.0/3.develop/demo/C%26C%2B%2B/vs-c-ob-capi/1%E6%89%93%E5%BC%80%E9%A1%B9%E7%9B%AE.png)
      2. 浏览到 **c-oceanbase-odbc 项目** 的文件夹，选择项目文件（`c-oceanbase-odbc.sln` 或者 `c-oceanbase-odbc.vcxproj`），然后点击 **打开**。

        ![2](https://obbusiness-private.oss-cn-shanghai.aliyuncs.com/doc/img/observer-enterprise/V4.2.0/3.develop/demo/C%26C%2B%2B/vs-c-ob-odbc/1%E6%89%93%E5%BC%80%E9%A1%B9%E7%9B%AE.png)

### 步骤二：配置 c-oceanbase-odbc 项目属性

1. 打开项目的属性页。

   在 **解决方案管理器中** 右键单击选定的项目，然后在上下文菜单中选择 **属性**，或者在 Visual Studio 的顶部菜单栏中选择 **项目** -> **属性**，或者使用快捷键 Alt + Enter。
 2. 配置管理器设置。

      1. 在属性页中选择上方找到 **配置(C)** 下拉菜单。在下拉菜单中，选择 **Debug**。
      2. 在属性页中选择上方找到 **平台(P)** 下拉菜单。在下拉菜单中，选择 **x64**。

   ![3](https://obbusiness-private.oss-cn-shanghai.aliyuncs.com/doc/img/observer-enterprise/V4.2.0/3.develop/demo/C%26C%2B%2B/vs-c-ob-odbc/2%E5%B1%9E%E6%80%A7_%E5%B9%B3%E5%8F%B0.png)
 3. 字符集设置。

   在属性页中选择 **高级** 选项卡，找到 **字符集** 一栏。在下拉菜单中，选择 **使用多字节字符集**。

   ![4](https://obbusiness-private.oss-cn-shanghai.aliyuncs.com/doc/img/observer-enterprise/V4.2.0/3.develop/demo/C%26C%2B%2B/vs-c-ob-odbc/3%E5%B1%9E%E6%80%A7_%E5%AD%97%E7%AC%A6%E9%9B%86.png)

### 步骤三：获取 OceanBase 数据库连接信息

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

**示例如下：**

```shell
obclient -hxxx.xxx.xxx.xxx -P2881 -usys@oracle001 -p******

```

**参数说明：**

- `-h`：提供 OceanBase 数据库连接 IP。ODP 连接方式使用的是一个 ODP 地址；直连方式使用的是 OBServer 节点的 IP 地址。
 - `-P`：提供 OceanBase 数据库连接端口。ODP 连接的方式默认是 `2883`，在部署 ODP 时可自定义；直连方式默认是 `2881`，在部署 OceanBase 数据库时可自定义。
 - `-u`：提供租户的连接账户。ODP 连接的常用格式有：`用户名@租户名#集群名` 或者 `集群名:租户名:用户名`；直连方式格式：`用户名@租户名`。
 - `-p`：提供账户密码。

更多连接串的信息，请参见 [通过 OBClient 连接 OceanBase 租户](https://www.oceanbase.com/docs/common-oceanbase-database-cn-1000000004476142)。

### 步骤四：修改 c-oceanbase-odbc 项目中的数据库连接信息

根据 **步骤三：获取 OceanBase 数据库连接信息** 中的信息修改 `test_tbl1.cpp` 文件中的数据库连接信息。

**示例如下：**

```c
char* mydriver = (char*)"Driver={OceanBase ODBC 2.0 Driver};Server=xxx.xxx.xxx.xxx;Port=2881;Database=sys;User=sys@oracle001;Password=******;Option=3;";

```

![5](https://obbusiness-private.oss-cn-shanghai.aliyuncs.com/doc/img/observer-enterprise/V4.2.0/3.develop/demo/C%26C%2B%2B/vs-c-ob-odbc/4%E8%BF%9E%E6%8E%A5%E4%BF%A1%E6%81%AF.png)

### 步骤五：构建项目

选择 **生成** 菜单，然后选择 **生成解决方案**。构建过程中会显示编译器的输出和任何错误或警告信息。

![7](https://obbusiness-private.oss-cn-shanghai.aliyuncs.com/doc/img/observer-enterprise/V4.2.0/3.develop/demo/C%26C%2B%2B/vs-c-ob-capi/7%E7%94%9F%E6%88%90%E6%88%90%E5%8A%9F.png)

### 步骤六：运行应用程序

选择 **调试** 菜单，然后选择 **开始调试** 或者 **开始执行(不调试)** 来运行的应用程序。

### 步骤七：查看输出结果

输出结果将显示在调试控制台中。您可以根据程序的设计逻辑和代码来判断如何处理输出。

![8](https://obbusiness-private.oss-cn-shanghai.aliyuncs.com/doc/img/observer-enterprise/V4.2.0/3.develop/demo/C%26C%2B%2B/vs-c-ob-odbc/5%E8%BF%90%E8%A1%8C%E7%BB%93%E6%9E%9C.png)

## 项目代码介绍

点击 [c-oceanbase-odbc](https://obbusiness-private.oss-cn-shanghai.aliyuncs.com/doc/img/observer-enterprise/V4.2.0/3.develop/demo/C%26C%2B%2B/c-oceanbase-odbc.zip) 下载项目代码，是一个名称为 `c-oceanbase-odbc.zip` 的压缩包。

解压后，得到一个名为 `c-oceanbase-odbc` 的文件夹。目录结构如下所示：

```shell
c-oceanbase-odbc
├─ c-oceanbase-odbc.sln
├─ c-oceanbase-odbc.vcxproj
├─ c-oceanbase-odbc.vcxproj.filters
├─ c-oceanbase-odbc.vcxproj.user
└─ test_tbl1.cpp

```

**文件说明：**

- `c-oceanbase-odbc.sln`：Visual Studio 的解决方案文件，用于管理一个或多个项目。
 - `c-oceanbase-odbc.vcxproj`：Visual Studio 的项目文件，用于描述一个 C/C++ 项目的结构和配置。
 - `c-oceanbase-odbc.vcxproj.filters`：Visual Studio 的项目过滤器文件，用于定义项目中文件的目录结构和组织方式。
 - `c-oceanbase-odbc.vcxproj.user`：用于存储用户特定的项目设置的文件。
 - `test_tbl1.cpp`：定义数据表的结构和实现数据表操作的源代码文件。

### test_tbl1.cpp 文件代码介绍

`test_tbl1.cpp` 文件用于定义名称为 `test_tbl1` 的数据表，实现了数据表的创建、插入数据和查询操作。

本文 `test_tbl1.cpp` 文件的代码主要包括以下几个部分：

1. 引用头文件。

   引用头文件 `stdio.h`、`assert.h`、`windows.h`、`sql.h` 和 `sqlext.h`。

   **代码如下：**

   ```c
   #include <stdio.h>
   #include <assert.h>
   #include <windows.h>
   #include <sql.h>
   #include <sqlext.h>

   ```
 2. 定义函数 `odbc_print_error`。

   这个函数的作用是在程序运行过程中，如果出现 ODBC 相关的错误，就可以调用这个函数，打印出错误信息。具体步骤如下：

      1. 定义函数名称为 `odbc_print_error`，并指定参数 `SQLSMALLINT HandleType` 和 `SQLHANDLE Handle`，用来指定错误信息所对应的句柄类型和句柄。
      2. 定义用于存储从 ODBC 中获取错误信息的变量。这些变量的类型和名称都是 ODBC API 中定义的数据类型和名称。
      3. 使用 `SQLGetDiagRec()` 获取 ODBC 中最后一次生成的错误信息。在这个函数调用后，`SQLState`、`NativeError` 和 `SQLMessage` 数组中存储了错误信息的相关内容。
      4. 使用 `fprintf` 函数将错误信息打印到标准输出流中。`[%s] (%d) %s\n` 是打印格式，它使用了类似于 `printf` 函数的格式化字符串。`%s` 用于打印字符串类型的数据，`%d` 用于打印整型数据，`\n` 表示换行。`SQLState`、`NativeError` 和 `SQLMessage` 分别对应了格式化字符串中的三个参数，表示要打印出的错误信息内容。

   **代码如下：**

   ```c
   static void odbc_print_error(SQLSMALLINT HandleType, SQLHANDLE Handle)
   {
       SQLCHAR SQLState[6];
       SQLINTEGER NativeError;
       SQLCHAR SQLMessage[SQL_MAX_MESSAGE_LENGTH] = { 0 };
       SQLSMALLINT TextLengthPtr;
       SQLGetDiagRec(HandleType, Handle, 1, SQLState, &NativeError, SQLMessage, SQL_MAX_MESSAGE_LENGTH, &TextLengthPtr);
       fprintf(stdout, "[%s] (%d) %s\n", SQLState, NativeError, SQLMessage);
   }

   ```
 3. 定义函数 `ASSERT_CHECK`。

   这个函数的作用是用于检查并处理 ODBC 函数调用的返回值，即检查 ODBC API 函数的返回值是否出现错误，如果出现错误就打印错误信息，并退出程序。具体步骤如下：

      1. 定义宏名称为 `ASSERT_CHECK`，并指定参数 `SQLSMALLINT HandleType`、`SQLHANDLE Handle` 和 `SQLRETURN rcode`，分别是 ODBC 句柄类型、ODBC 句柄和 ODBC API 函数调用的返回值。
      2. 使用 `if` 语句对 ODBC API 函数的返回值进行判断，如果返回值不等于 `SQL_SUCCESS` 或者 `SQL_SUCCESS_WITH_INFO`，就表示函数调用出现了错误。
      3. 调用 `odbc_print_error` 函数，打印出 ODBC 错误信息。
      4. 调用 `assert` 函数，用于在程序运行过程中进行断言检查，即 ODBC 函数调用出现了错误，那么程序就会中断。

   **代码如下：**

   ```c
   static void ASSERT_CHECK(SQLSMALLINT HandleType, SQLHANDLE Handle, SQLRETURN rcode)
   {
       if (rcode != SQL_SUCCESS && rcode != SQL_SUCCESS_WITH_INFO) {
           odbc_print_error(HandleType, Handle);
           assert(0);
       }
   }

   ```
 4. 定义函数 `main`。

   定义程序的入口函数 `main`，返回一个整数值。在 `main` 函数中，编写了与数据库连接、数据操作相关的代码。

   **代码如下：**

   ```c
   int main() {
       // 申请环境句柄
       // 设置ODBC版本的环境属性
       // 分配连接句柄
       // 连接数据源
       // 创建表
       // 插入数据
       // 查询数据
       // 清理工作, 释放具体的资源句柄
   }

   ```
 5. 定义变量。

   定义变量 `henv`，它是 ODBC 环境句柄类型的对象，用于管理 ODBC 连接和资源的分配。`OutConnStr` 和 `OutConnStrLen` 用于存储连接字符串和字符串的长度，这些参数在连接到数据库时传递给 `SQLDriverConnect` 函数，以获得成功连接到数据库时的返回值和一些其他的连接信息。

   **代码如下：**

   ```c
       HENV henv;
       SQLCHAR OutConnStr[255];
       SQLSMALLINT OutConnStrLen;

   ```
 6. 申请环境句柄。

   通过 `SQLAllocHandle` 函数分配一个 ODBC 环境句柄，并通过 `ASSERT_CHECK` 函数检查分配句柄的结果，确保分配成功。具体步骤如下：

      1. `SQLAllocHandle` 函数执行后，返回一个 `SQLRETURN` 类型的值，指示函数的执行结果。在代码中，这个返回值被存储在 `rcode` 变量中。`SQLAllocHandle` 函数的参数如下：

             - `SQL_HANDLE_ENV`：指定要分配的句柄的类型。在这里，它是 `SQL_HANDLE_ENV`，表示要分配一个环境句柄。
             - `SQL_NULL_HANDLE`：指定父句柄。在这里，它是 `SQL_NULL_HANDLE`，表示没有父句柄。
             - `&henv`：是一个指向存储分配句柄的变量的指针。在这里，它是 `henv`，即环境句柄的变量。
      2. `ASSERT_CHECK` 函数被用于检查 `SQLAllocHandle` 函数的返回值 `rcode`。如果 `rcode` 不是 `SQL_SUCCESS` 或 `SQL_SUCCESS_WITH_INFO`，即分配句柄失败，那么`ASSERT_CHECK` 函数将调用 `odbc_print_error` 函数打印出错误信息，并使用 `assert` 宏终止程序的执行。

   **代码如下：**

   ```c
       SQLRETURN rcode = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv);
       ASSERT_CHECK(SQL_HANDLE_ENV, henv, rcode);

   ```
 7. 设置 ODBC 版本的环境属性。

   通过 `SQLSetEnvAttr` 函数设置 ODBC 环境的属性，它可以设置一些环境级别的属性，以影响数据库连接和驱动程序的行为，并通过 `ASSERT_CHECK` 函数检查设置属性的结果，确保设置成功。具体步骤如下：

      1. `SQLSetEnvAttr` 函数执行后，返回一个 `SQLRETURN` 类型的值，指示函数的执行结果。在代码中，这个返回值被存储在 `rcode` 变量中。`SQLSetEnvAttr` 函数的参数如下：

             - `henv`：是 ODBC 环境句柄，指定要设置属性的环境对象。
             - `SQL_ATTR_ODBC_VERSION`：指定要设置的环境属性类型。在这里，它是 `SQL_ATTR_ODBC_VERSION`，表示要设置 ODBC 版本的属性。
             - `(void*)SQL_OV_ODBC3`：是属性值的指针。在这里，它是 `SQL_OV_ODBC3`，表示将 ODBC 版本设置为 ODBC 3.x 版本。
             - `0`：是属性值的长度。在这里，由于属性值是一个枚举常量，所以长度是 `0`。
      2. `ASSERT_CHECK` 函数被用于检查 `SQLSetEnvAttr` 函数的返回值 `rcode`。如果 `rcode` 不是 `SQL_SUCCESS` 或 `SQL_SUCCESS_WITH_INFO`，即设置属性失败，那么`ASSERT_CHECK` 函数将调用 `odbc_print_error` 函数打印出错误信息，并使用 `assert` 宏终止程序的执行。

   **代码如下：**

   ```c
       rcode = SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION, (void*)SQL_OV_ODBC3, 0);
       ASSERT_CHECK(SQL_HANDLE_ENV, henv, rcode);

   ```
 8. 分配连接句柄。

   通过 `SQLAllocHandle` 函数分配一个 `ODBC` 连接句柄，并通过 `ASSERT_CHECK` 函数检查分配句柄的结果，确保分配成功。具体步骤如下：

             - `SQL_HANDLE_DBC`：指定要分配的句柄的类型。在这里，它是 `SQL_HANDLE_DBC`，表示要分配一个连接句柄。
             - `henv`：是一个已分配的ODBC环境句柄，作为父句柄，用于与连接句柄关联。
             - `&hdbc`：是一个指向存储分配的连接句柄的变量的指针。
      2. `ASSERT_CHECK` 函数被用于检查 `SQLAllocHandle` 函数的返回值 `rcode`。如果 `rcode` 不是 `SQL_SUCCESS` 或 `SQL_SUCCESS_WITH_INFO`，即分配句柄失败，那么 `ASSERT_CHECK` 函数将调用 `odbc_print_error` 函数打印出错误信息，并使用 `assert` 宏终止程序的执行。

   **代码如下：**

   ```c
       SQLHDBC hdbc;
       rcode = SQLAllocHandle(SQL_HANDLE_DBC, henv, &hdbc);
       ASSERT_CHECK(SQL_HANDLE_DBC, hdbc, rcode);

   ```
 9. 连接数据源。

   使用 `SQLDriverConnect` 函数连接到指定的 ODBC 数据源，并通过 `ASSERT_CHECK` 函数检查连接操作的结果，确保连接成功。具体步骤如下：

      1. 定义一个连接字符串 `mydriver`，用于描述连接到数据库所需的详细信息。该字符串包含了以下几个部分：

             - `Driver={OceanBase ODBC 2.0 Driver}`：指定使用的 ODBC 驱动程序为 OceanBase ODBC 2.0 Driver。
             - `Server=your_ip`：指定数据库服务器的 IP 地址。
             - `Port=your_port`：指定连接数据库时使用的端口号。
             - `Database=your_schema`：指定要连接的数据库名称。
             - `User=your_use`：指定连接到数据库时使用的用户名。
             - `Password=your_password`：指定连接到数据库时使用的密码。
             - `Option=3`：指定连接选项，其值为 `3`，表示使用 TCP/IP 连接。
      2. 使用 `SQLDriverConnect` 函数连接到指定的 ODBC 数据源。函数执行后，返回一个 SQLRETURN 类型的值，指示函数的执行结果。在代码中，这个返回值被存储在 rcode 变量中。该函数的参数如下：

             - `hdbc`：是 ODBC 连接句柄，用于与数据源建立连接。
             - `NULL`：是一个保留参数，未使用。
             - `mydriver`：是连接字符串，它包含连接数据库所需的所有信息，如驱动程序名称、数据库地址、端口号、数据库名称、用户名和密码等。
             - `strlen((char*)mydriver) + 1`：是连接字符串的长度。
             - `OutConnStr`：是一个用于存储连接字符串的SQLCHAR类型的缓冲区。
             - `255`：是缓冲区的长度。
             - `&OutConnStrLen`：是一个指向存储连接字符串实际长度的变量的指针。
             - `SQL_DRIVER_NOPROMPT`：是一个连接标志，用于指示连接时不显示任何提示框。
      3. `ASSERT_CHECK` 函数被用于检查 `SQLDriverConnect` 函数的返回值 `rcode`。如果 `rcode` 不是 `SQL_SUCCESS` 或 `SQL_SUCCESS_WITH_INFO`，即连接失败，那么`ASSERT_CHECK` 函数将调用 `odbc_print_error` 函数打印出错误信息，并使用 `assert` 宏终止程序的执行。

   **代码如下：**

   ```c
       char* mydriver = (char*)"Driver={OceanBase ODBC 2.0 Driver};Server=your_ip;Port=your_port;Database=your_schema;User=your_use;Password=your_password;Option=3;";
       rcode = SQLDriverConnect(hdbc, NULL, (SQLCHAR*)mydriver, strlen((char*)mydriver) + 1, OutConnStr, 255, &OutConnStrLen, SQL_DRIVER_NOPROMPT);
       ASSERT_CHECK(SQL_HANDLE_DBC, hdbc, rcode);

   ```

   **连接 OceanBase 数据库所需要的参数说明：**

      - `your_ip`：提供 OceanBase 数据库连接 IP。ODP 连接方式使用的是一个 ODP 地址；直连方式使用的是 OBServer 节点的 IP 地址。
      - `your_port`：提供 OceanBase 数据库连接端口。ODP 连接的方式默认是 `2883`，在部署 ODP 时可自定义；直连方式默认是 `2881`，在部署 OceanBase 数据库时可自定义。
      - `your_schema`：需要访问的 Schema 名称。
      - `your_user`：提供租户的连接账户。ODP 连接的方式格式：`用户名@租户名#集群名` 或者 `集群名:租户名:用户名`；直连方式格式：`用户名@租户名`。
      - `your_password`：提供账户密码。
 10. 创建表。

    通过 `SQLAllocHandle` 函数分配一个 ODBC 语句句柄，然后使用 `SQLExecDirect` 函数执行一个 SQL 语句来创建一个表。代码还使用 `ASSERT_CHECK` 函数来检查句柄分配和语句执行的结果，确保操作成功。最后，使用 `SQLFreeHandle` 函数释放语句句柄，以释放资源。具体步骤如下：

       1. 声明一个 ODBC 语句句柄 `stmt`。
       2. 使用 `SQLAllocHandle` 函数分配一个 ODBC 语句句柄。
       3. 使用 `ASSERT_CHECK` 函数检查 `SQLAllocHandle` 函数的返回值 `rcode`，确保句柄分配成功。
       4. 使用 `SQLExecDirect` 函数执行一个 SQL 语句。在这里，它执行了一个 `CREATE TABLE` 语句来创建名为 `test_tbl1` 的表。
       5. 使用 `ASSERT_CHECK` 函数检查 `SQLExecDirect` 函数的返回值 `rcode`，确保语句执行成功。
       6. 使用 `SQLFreeHandle` 函数释放 `ODBC` 语句句柄。

    **代码如下：**

    ```c
        SQLHSTMT stmt;
        rcode = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &stmt);
        ASSERT_CHECK(SQL_HANDLE_STMT, stmt, rcode);

        rcode = SQLExecDirect(stmt, (SQLCHAR*)"CREATE TABLE test_tbl1(id NUMBER PRIMARY KEY, name VARCHAR2(50),age NUMBER NOT NULL)", SQL_NTS);
        ASSERT_CHECK(SQL_HANDLE_STMT, stmt, rcode);

        SQLFreeHandle(SQL_HANDLE_STMT, stmt);

    ```
 11. 插入数据。

    通过 `SQLAllocHandle` 函数分配一个 ODBC 语句句柄，然后使用 `SQLExecDirect` 函数执行一个 SQL 语句向数据库表中插入数据。代码还使用 `ASSERT_CHECK` 函数来检查句柄分配和语句执行的结果，确保操作成功。最后，使用 `SQLFreeHandle` 函数释放语句句柄，以释放资源。具体步骤如下：

       1. 使用 `SQLAllocHandle` 函数分配一个 ODBC 语句句柄。
       2. 使用 `ASSERT_CHECK` 函数检查 `SQLAllocHandle` 函数的返回值 `rcode`，确保句柄分配成功。
       3. 使用 `SQLExecDirect` 函数执行一个 SQL 语句。在这里，它执行了一个 `INSERT INTO` 语句，向 `test_tbl1` 表中插入三条记录。
       4. 使用 `ASSERT_CHECK` 函数检查 `SQLExecDirect` 函数的返回值 `rcode`，确保语句执行成功。
       5. 使用 `SQLFreeHandle` 函数释放 ODBC 语句句柄。

    **代码如下：**

    ```c
        rcode = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &stmt);
        ASSERT_CHECK(SQL_HANDLE_STMT, stmt, rcode);

        rcode = SQLExecDirect(stmt, (SQLCHAR*)"INSERT INTO test_tbl1 (id,name,age) VALUES  (1,'Tom', 18),(2,'Jerry', 20),(3,'Bob', 22)", SQL_NTS);
        ASSERT_CHECK(SQL_HANDLE_STMT, stmt, rcode);

    ```
 12. 查询数据。

    通过 `SQLAllocHandle` 函数分配一个 ODBC 语句句柄，然后使用 `SQLExecDirect` 函数执行一个 SQL 语句来获取结果集。接着，使用 `SQLBindCol` 函数将结果集的列绑定到变量上，然后使用 `SQLFetch` 函数逐行获取结果集。在 `while` 循环中，根据 `rcode` 的值打印出结果集中的数据。最后，使用 `SQLFreeHandle` 函数释放语句句柄，以释放资源。具体步骤如下：

       1. 使用 `SQLAllocHandle` 函数分配一个 ODBC 语句句柄。
       2. 使用 `ASSERT_CHECK` 函数检查 `SQLAllocHandle` 函数的返回值 `rcode`，确保句柄分配成功。
       3. 使用 `SQLExecDirect` 函数执行一个 SQL 语句。在这里，它执行了一个 `SELECT` 语句，从 `test_tbl1` 表中检索所有行。
       4. 使用 `ASSERT_CHECK` 函数检查 `SQLExecDirect` 函数的返回值 `rcode`，确保语句执行成功。
       5. 声明一个 `SQLLEN` 类型的变量 `res`，用于存储绑定列操作的结果。
       6. 声明两个 `SQLINTEGER` 类型的变量 `id` 和 `age`，用于存储结果集中对应列的值。
       7. 声明一个 `SQLCHAR` 类型的数组 `name`，用于存储结果集中对应列的值。
       8. 使用 `SQLBindCol` 函数将结果集的第一列绑定到变量 `id` 上。
       9. 使用 `SQLBindCol` 函数将结果集的第二列绑定到数组 `name` 上。
       10. 使用 `SQLBindCol` 函数将结果集的第三列绑定到变量 `age` 上。
       11. 使用 `SQLFetch` 函数获取结果集的行，并将行中的数据存储到绑定的变量中。`while` 循环会一直执行，直到所有行都被取完。
       12. 在 `while` 循环中，通过判断 `rcode` 的值，打印出对应行的数据。如果 `rcode` 为 `SQL_ERROR`，则打印出错误信息。
       13. 使用 `SQLFreeHandle` 函数释放 ODBC 语句句柄。

    **代码如下：**

        rcode = SQLExecDirect(stmt, (SQLCHAR*)"SELECT * FROM test_tbl1", SQL_NTS);
        ASSERT_CHECK(SQL_HANDLE_STMT, stmt, rcode);

        SQLLEN res = SQL_NTS;
        SQLINTEGER id, age;
        SQLCHAR name[255];
        SQLBindCol(stmt, 1, SQL_C_SLONG, &id, sizeof(id), &res);
        SQLBindCol(stmt, 2, SQL_C_CHAR, name, sizeof(name), &res);
        SQLBindCol(stmt, 3, SQL_C_SLONG, &age, sizeof(age), &res);

        while ((rcode = SQLFetch(stmt)) != SQL_NO_DATA_FOUND)
        {
            if (rcode == SQL_ERROR) {
                printf("sql error!\n");
            }
            else {
                printf("id:%d, name:%s, age:%ld\n", id, name, age);
            }
        }

    ```
 13. 清理工作, 释放具体的资源句柄。

    断开与数据库的连接并释放相关的 ODBC 句柄和环境句柄，以释放资源。通过调用 SQLDisconnect 函数和 SQLFreeHandle 函数，程序可以正确地关闭与数据库的连接和释放相关句柄。最后，通过返回0表示程序执行成功。具体步骤如下：

       1. 使用 SQLDisconnect 函数断开与数据库的连接。
       2. 使用 SQLFreeHandle 函数释放数据库连接句柄。
       3. 使用 SQLFreeHandle 函数释放 ODBC 环境句柄。
       4. 返回 0，表示程序执行成功。

    **代码如下：**

    ```c
        SQLDisconnect(hdbc);
        SQLFreeHandle(SQL_HANDLE_DBC, hdbc);
        SQLFreeHandle(SQL_HANDLE_ENV, henv);

        return 0;

    ```

#### 完整的代码展示

    test_tbl1.cpp

static void odbc_print_error(SQLSMALLINT HandleType, SQLHANDLE Handle)
{
    SQLCHAR SQLState[6];
    SQLINTEGER NativeError;
    SQLCHAR SQLMessage[SQL_MAX_MESSAGE_LENGTH] = { 0 };
    SQLSMALLINT TextLengthPtr;
    SQLGetDiagRec(HandleType, Handle, 1, SQLState, &NativeError, SQLMessage, SQL_MAX_MESSAGE_LENGTH, &TextLengthPtr);
    fprintf(stdout, "[%s] (%d) %s\n", SQLState, NativeError, SQLMessage);
}

static void ASSERT_CHECK(SQLSMALLINT HandleType, SQLHANDLE Handle, SQLRETURN rcode)
{
    if (rcode != SQL_SUCCESS && rcode != SQL_SUCCESS_WITH_INFO) {
        odbc_print_error(HandleType, Handle);
        assert(0);
    }
}

int main()
{
    HENV henv;
    SQLCHAR OutConnStr[255];
    SQLSMALLINT OutConnStrLen;

    SQLRETURN rcode = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv);
    ASSERT_CHECK(SQL_HANDLE_ENV, henv, rcode);

    rcode = SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION, (void*)SQL_OV_ODBC3, 0);
    ASSERT_CHECK(SQL_HANDLE_ENV, henv, rcode);

    SQLHDBC hdbc;
    rcode = SQLAllocHandle(SQL_HANDLE_DBC, henv, &hdbc);
    ASSERT_CHECK(SQL_HANDLE_DBC, hdbc, rcode);

    char* mydriver = (char*)"Driver={OceanBase ODBC 2.0 Driver};Server=your_ip;Port=your_port;Database=your_schema;User=your_use;Password=your_password;Option=3;";
    rcode = SQLDriverConnect(hdbc, NULL, (SQLCHAR*)mydriver, strlen((char*)mydriver) + 1, OutConnStr, 255, &OutConnStrLen, SQL_DRIVER_NOPROMPT);
    ASSERT_CHECK(SQL_HANDLE_DBC, hdbc, rcode);

    SQLHSTMT stmt;
    rcode = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &stmt);
    ASSERT_CHECK(SQL_HANDLE_STMT, stmt, rcode);

    rcode = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &stmt);
    ASSERT_CHECK(SQL_HANDLE_STMT, stmt, rcode);

    SQLDisconnect(hdbc);
    SQLFreeHandle(SQL_HANDLE_DBC, hdbc);
    SQLFreeHandle(SQL_HANDLE_ENV, henv);

    return 0;
}

```

## 相关文档

- 更多连接 OceanBase 数据库的信息，请参见 [连接方式概述](https://www.oceanbase.com/docs/common-oceanbase-database-cn-1000000004476144)。
 - 更多 OceanBase Connector/ODBC 的信息，请参见 [OceanBase Connector/ODBC](https://www.oceanbase.com/docs/oceanbase-connector-odbc-cn)。

 上一篇 下一篇 ![有帮助](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) 咨询热线
