在 OceanBase 数据库 MySQL 模式下,用户可以直接使用 MySQL 官方提供的 Connector 来使用 OceanBase 数据库(暂不支持 8.0 的驱动),在 OceanBase 数据库 Oracle 模式下,需要使用 OceanBase 自研的数据库驱动。OceanBase 数据库驱动同时支持 OceanBase 数据库的 MySQL/Oracle 两种协议,在使用时可以自动识别 OceanBase 数据库的运行模式是 MySQL 还是 Oracle,无需额外设置。OceanBase 数据库支持各类语言的数据库驱动,下面介绍几种常见的语言及标准。

OCI 驱动

OceanBase 提供了基于 OCI 接口的数据库驱动,兼容了 Oracle 数据库 OCI 接口的方法名和函数名,对于试用 OCI 接口编程的应用程序在进行移植时,无需做大量业务改造即可非常方便的适配到 OceanBase 数据库。

样例代码:

  1. /**********************************************************
  2. * Copyright(C) 2014 - 2020 Alibaba Inc. All Rights Reserved.
  3. *
  4. * Filename: example.c
  5. * Description: ----
  6. * Create: 2020-07-07 10:14:59
  7. * Last Modified: 2020-07-07 10:14:59
  8. ***********************************************************/
  9. #include <stdio.h>
  10. #include <string.h>
  11. #include <stdlib.h>
  12. #include <malloc.h>
  13. #include "oci.h"
  14. /*声明句柄*/
  15. OCIEnv *envhp; /*环境句柄*/
  16. OCISvcCtx *svchp; /*服务环境句柄*/
  17. OCIServer *srvhp; /*服务器句柄*/
  18. OCISession *authp; /*会话句柄*/
  19. OCIStmt *stmthp; /*语句句柄*/
  20. OCIDescribe *dschp; /*描述句柄*/
  21. OCIError *errhp; /*错误句柄*/
  22. OCIDefine *defhp[3]; /*定义句柄*/
  23. OCIBind *bidhp[4]; /*绑定句柄*/
  24. sb2 ind[3]; /*指示符变量*/
  25. /*绑定select结果集的参数*/
  26. int szpersonid; /*存储personid列*/
  27. text szsex[2]; /*存储sex列*/
  28. text szname[10]; /*存储name列*/
  29. text szemail[10]; /*存储mail列*/
  30. char sql[256]; /*存储执行的sql语句*/
  31. static text* SQL_DROP_TB = (text*)"drop table person";
  32. static text* SQL_CREATE_TB = (text*)"create table person(personid number, sex varchar2(256), name varchar2(256), email varchar2(256))";
  33. void checkerr(OCIError *errhp, sword status, const char* filename, int line) {
  34. text errbuf[512];
  35. sb4 errcode = 0;
  36. switch (status)
  37. {
  38. case OCI_SUCCESS:
  39. break;
  40. case OCI_SUCCESS_WITH_INFO:
  41. (void) OCIErrorGet((dvoid *)errhp, (ub4) 1, (text *) NULL, &errcode,
  42. errbuf, (ub4) sizeof(errbuf), OCI_HTYPE_ERROR);
  43. (void) printf("%s:%d Error - OCI_SUCCESS_WITH_INFO now get is %d:%.*s\n", filename, line, errcode, 512, errbuf);
  44. break;
  45. case OCI_NEED_DATA:
  46. (void) printf("%s:%d Error - OCI_NEED_DATA\n", filename, line);
  47. break;
  48. case OCI_NO_DATA:
  49. (void) printf("%s:%d Error - OCI_NODATA\n", filename, line);
  50. break;
  51. case OCI_ERROR:
  52. (void) OCIErrorGet((dvoid *)errhp, (ub4) 1, (text *) NULL, &errcode,
  53. errbuf, (ub4) sizeof(errbuf), OCI_HTYPE_ERROR);
  54. (void) printf("%s:%d Error - now get is %d:%.*s\n", filename, line, errcode, 512, errbuf);
  55. break;
  56. case OCI_INVALID_HANDLE:
  57. (void) printf("%s:%d Error - OCI_INVALID_HANDLE\n", filename, line);
  58. break;
  59. case OCI_STILL_EXECUTING:
  60. (void) printf("%s:%d Error - OCI_STILL_EXECUTE\n", filename, line);
  61. break;
  62. case OCI_CONTINUE:
  63. (void) printf("%s:%d Error - OCI_CONTINUE\n", filename, line);
  64. break;
  65. default:
  66. break;
  67. }
  68. }
  69. #define OCI_CHECK_RET(errhp, function) \
  70. checkerr(errhp, function, __FILE__, __LINE__)
  71. /************************************************************************/
  72. /*查询person表*/
  73. /************************************************************************/
  74. void query_tables() {
  75. sword status = OCI_SUCCESS;
  76. memset(sql, 0, sizeof(sql));
  77. strcpy(sql, "select personid, name, email from person");
  78. /*准备SQL语句*/
  79. OCI_CHECK_RET(errhp, OCIStmtPrepare(stmthp, errhp, (text *)sql, strlen(sql), OCI_NTV_SYNTAX, OCI_DEFAULT));
  80. /*绑定输出列*/
  81. OCI_CHECK_RET(errhp, OCIDefineByPos(stmthp, &defhp[0], errhp, 1, &szpersonid,
  82. sizeof(szpersonid), SQLT_INT, &ind[0], 0, 0, OCI_DEFAULT));
  83. OCI_CHECK_RET(errhp, OCIDefineByPos(stmthp, &defhp[1], errhp, 2, (ub1 *)szname,
  84. sizeof(szname), SQLT_STR, &ind[1], 0, 0, OCI_DEFAULT));
  85. OCI_CHECK_RET(errhp, OCIDefineByPos(stmthp, &defhp[2], errhp, 3, (ub1 *)szemail,
  86. sizeof(szemail), SQLT_STR, &ind[2], 0, 0, OCI_DEFAULT));
  87. /*执行SQL语句*/
  88. OCI_CHECK_RET(errhp, OCIStmtExecute(svchp, stmthp, errhp, (ub4)0, 0, NULL, NULL,
  89. OCI_DEFAULT));
  90. printf("%-10s%-10s%-10s\n", "PERSONID", "NAME", "EMAIL");
  91. while ((status = OCIStmtFetch(stmthp, errhp, 1, OCI_FETCH_NEXT, OCI_DEFAULT)) == OCI_SUCCESS) {
  92. printf("%-10d", szpersonid);
  93. printf("%-10s", szname);
  94. printf("%-10s\n", szemail);
  95. }
  96. if (OCI_NO_DATA != status) {
  97. printf("error ! error ! error ! err=%d\n", status);
  98. } else {
  99. printf("finish fetch data\n");
  100. }
  101. }
  102. void insert_tables() {
  103. memset(sql, 0, sizeof(sql));
  104. strcpy(sql, "insert into person values(:personid,:sex,:name,:email)");
  105. /*准备SQL语句*/
  106. OCI_CHECK_RET(errhp, OCIStmtPrepare(stmthp, errhp, (text *)sql, strlen(sql), OCI_NTV_SYNTAX,
  107. OCI_DEFAULT));
  108. /*绑定输入列*/
  109. OCI_CHECK_RET(errhp, OCIBindByName(stmthp, &bidhp[0], errhp, (const OraText*)":personid", 9, &szpersonid,
  110. sizeof(szpersonid), SQLT_INT, NULL, NULL, NULL, 0, NULL, 0));
  111. OCI_CHECK_RET(errhp, OCIBindByName(stmthp, &bidhp[1], errhp, (const OraText*)":sex", 4, szsex,
  112. sizeof(szsex), SQLT_STR, NULL, NULL, NULL, 0, NULL, 0));
  113. OCI_CHECK_RET(errhp, OCIBindByName(stmthp, &bidhp[2], errhp, (const OraText*)":name", 5, szname,
  114. sizeof(szname), SQLT_STR, NULL, NULL, NULL, 0, NULL, 0));
  115. OCI_CHECK_RET(errhp, OCIBindByName(stmthp, &bidhp[3], errhp, (const OraText*)":email", 6, szemail,
  116. sizeof(szemail), SQLT_STR, NULL, NULL, NULL, 0, NULL, 0));
  117. /*设置输入参数*/
  118. szpersonid = 1;
  119. memset(szsex, 0, sizeof(szsex));
  120. strcpy((char*)szsex, "M");
  121. memset(szname, 0, sizeof(szname));
  122. strcpy((char*)szname, "obtest");
  123. memset(szemail, 0, sizeof(szemail));
  124. strcpy((char*)szemail, "t@ob.com");
  125. /*执行SQL语句*/
  126. OCI_CHECK_RET(errhp, OCIStmtExecute(svchp, stmthp, errhp, (ub4)1, (ub4)0, (CONST OCISnapshot *)0, (OCISnapshot *)0, (ub4)OCI_DEFAULT));
  127. /*提交到数据库*/
  128. OCI_CHECK_RET(errhp, OCITransCommit(svchp, errhp, OCI_DEFAULT));
  129. while ((OCIStmtFetch(stmthp, errhp, 1, OCI_FETCH_NEXT, OCI_DEFAULT)) == OCI_SUCCESS) {
  130. printf("%-10d", szpersonid);
  131. printf("%-10s", szsex);
  132. printf("%-10s", szname);
  133. printf("%-10s\n", szemail);
  134. }
  135. printf("finish insert tables\n");
  136. }
  137. void update_tables() {
  138. memset(sql, 0, sizeof(sql));
  139. strcpy(sql, "update person set sex='M',name='test',email='test@mail' WHERE personid=1");
  140. /*准备SQL语句*/
  141. OCI_CHECK_RET(errhp, OCIStmtPrepare(stmthp, errhp, (text *)sql, strlen(sql), OCI_NTV_SYNTAX,
  142. OCI_DEFAULT));
  143. /*执行SQL语句*/
  144. OCI_CHECK_RET(errhp, OCIStmtExecute(svchp, stmthp, errhp, (ub4)1, (ub4)0, (CONST OCISnapshot *)0, (OCISnapshot *)0, (ub4)OCI_DEFAULT));
  145. /*提交到数据库*/
  146. OCI_CHECK_RET(errhp, OCITransCommit(svchp, errhp, OCI_DEFAULT));
  147. }
  148. void delete_tables() {
  149. memset(sql, 0, sizeof(sql));
  150. strcpy(sql, "delete from person WHERE personid = :personid");
  151. /*准备SQL语句*/
  152. OCI_CHECK_RET(errhp, OCIStmtPrepare(stmthp, errhp, (text *)sql, strlen(sql), OCI_NTV_SYNTAX,
  153. OCI_DEFAULT));
  154. /*绑定输入参数*/
  155. szpersonid = 1;
  156. OCI_CHECK_RET(errhp, OCIBindByPos(stmthp, &bidhp[0], errhp, 1, &szpersonid,
  157. sizeof(szpersonid), SQLT_INT, NULL, NULL, NULL, 0, NULL, 0));
  158. /*执行SQL语句*/
  159. OCI_CHECK_RET(errhp, OCIStmtExecute(svchp, stmthp, errhp, (ub4)1, (ub4)0, (CONST OCISnapshot *)0, (OCISnapshot *)0, (ub4)OCI_DEFAULT));
  160. /*提交到数据库*/
  161. OCI_CHECK_RET(errhp, OCITransCommit(svchp, errhp, OCI_DEFAULT));
  162. }
  163. int main(int argc, char *argv[]) {
  164. char strServerName[50];
  165. char strUserName[50];
  166. char strPassword[50];
  167. /*根据实际,设置服务器,用户名和密码*/
  168. strcpy(strServerName, "192.160.0.1/test");
  169. strcpy(strUserName, "test");
  170. strcpy(strPassword, "test");
  171. /*初始化OCI应用环境*/
  172. OCI_CHECK_RET(errhp, OCIInitialize(OCI_DEFAULT, NULL, NULL, NULL, NULL));
  173. /*初始化环境句柄*/
  174. OCI_CHECK_RET(errhp, OCIEnvInit(&envhp, OCI_DEFAULT, 0, 0));
  175. /*分配句柄*/
  176. OCI_CHECK_RET(errhp, OCIHandleAlloc(envhp, (dvoid **)&svchp, OCI_HTYPE_SVCCTX, 0, 0));
  177. /*服务器环境句柄*/
  178. OCI_CHECK_RET(errhp, OCIHandleAlloc(envhp, (dvoid **)&srvhp, OCI_HTYPE_SERVER, 0, 0));
  179. /*服务器句柄*/
  180. OCI_CHECK_RET(errhp, OCIHandleAlloc(envhp, (dvoid **)&authp, OCI_HTYPE_SESSION, 0, 0));
  181. /*会话句柄*/
  182. OCI_CHECK_RET(errhp, OCIHandleAlloc(envhp, (dvoid **)&errhp, OCI_HTYPE_ERROR, 0, 0));
  183. /*错误句柄*/
  184. OCI_CHECK_RET(errhp, OCIHandleAlloc(envhp, (dvoid **)&dschp, OCI_HTYPE_DESCRIBE, 0, 0));
  185. /*描述符句柄*/
  186. /*连接服务器*/
  187. OCI_CHECK_RET(errhp, OCIServerAttach(srvhp, errhp, (text *)strServerName,
  188. (sb4)strlen(strServerName), OCI_DEFAULT));
  189. /*设置用户名和密码*/
  190. OCI_CHECK_RET(errhp, OCIAttrSet(authp, OCI_HTYPE_SESSION, (text *)strUserName,
  191. (ub4)strlen(strUserName), OCI_ATTR_USERNAME, errhp));
  192. OCI_CHECK_RET(errhp, OCIAttrSet(authp, OCI_HTYPE_SESSION, (text *)strPassword,
  193. (ub4)strlen(strPassword), OCI_ATTR_PASSWORD, errhp));
  194. /*设置服务器环境句柄属性*/
  195. OCI_CHECK_RET(errhp, OCIAttrSet((dvoid *)svchp, (ub4)OCI_HTYPE_SVCCTX,
  196. (dvoid *)srvhp, (ub4)0, OCI_ATTR_SERVER, errhp));
  197. OCI_CHECK_RET(errhp, OCIAttrSet(svchp, OCI_HTYPE_SVCCTX, (dvoid *)authp,
  198. 0, OCI_ATTR_SESSION, errhp));
  199. /*创建并开始一个用户会话*/
  200. OCI_CHECK_RET(errhp, OCISessionBegin(svchp, errhp, authp, OCI_CRED_RDBMS, OCI_DEFAULT));
  201. OCI_CHECK_RET(errhp, OCIHandleAlloc(envhp, (dvoid **)&stmthp, OCI_HTYPE_STMT, 0, 0));
  202. /*语句句柄*/
  203. /************************************************************************/
  204. /*创建person表*/
  205. /************************************************************************/
  206. OCI_CHECK_RET(errhp, OCIStmtPrepare(stmthp, errhp, (text*)SQL_DROP_TB, strlen((char *)SQL_DROP_TB), OCI_NTV_SYNTAX, OCI_DEFAULT));
  207. OCI_CHECK_RET(errhp, OCIStmtExecute(svchp, stmthp, errhp, 1, 0, 0, 0, OCI_COMMIT_ON_SUCCESS));
  208. OCI_CHECK_RET(errhp, OCIStmtPrepare(stmthp, errhp, SQL_CREATE_TB, strlen((char *)SQL_CREATE_TB), OCI_NTV_SYNTAX, OCI_DEFAULT));
  209. OCI_CHECK_RET(errhp, OCIStmtExecute(svchp, stmthp, errhp, 1, 0, 0, 0, OCI_DEFAULT));
  210. /************************************************************************/
  211. /*查询person表*/
  212. /************************************************************************/
  213. query_tables();
  214. /************************************************************************/
  215. /*向person表插入一条数据*/
  216. /************************************************************************/
  217. insert_tables();
  218. query_tables();
  219. /************************************************************************/
  220. /*更新person表*/
  221. /************************************************************************/
  222. update_tables();
  223. query_tables();
  224. /************************************************************************/
  225. /*删除person表的ID为的数据,首先要在数据库中存在这条记录*/
  226. /************************************************************************/
  227. delete_tables();
  228. query_tables();
  229. /************************************************************************/
  230. /*结束释放资源*/
  231. /************************************************************************/
  232. //结束会话
  233. OCI_CHECK_RET(errhp, OCISessionEnd(svchp, errhp, authp, (ub4)0));
  234. //断开与数据库的连接
  235. OCI_CHECK_RET(errhp, OCIServerDetach(srvhp, errhp, OCI_DEFAULT));
  236. //释放OCI句柄
  237. OCI_CHECK_RET(errhp, OCIHandleFree((dvoid *)dschp, OCI_HTYPE_DESCRIBE));
  238. OCI_CHECK_RET(errhp, OCIHandleFree((dvoid *)stmthp, OCI_HTYPE_STMT));
  239. OCI_CHECK_RET(errhp, OCIHandleFree((dvoid *)errhp, OCI_HTYPE_ERROR));
  240. OCI_CHECK_RET(errhp, OCIHandleFree((dvoid *)authp, OCI_HTYPE_SESSION));
  241. OCI_CHECK_RET(errhp, OCIHandleFree((dvoid *)svchp, OCI_HTYPE_SVCCTX));
  242. OCI_CHECK_RET(errhp, OCIHandleFree((dvoid *)srvhp, OCI_HTYPE_SERVER));
  243. return 0;
  244. }

JDBC 驱动

OceanBase 数据库提供了基于 Java JDBC 标准的数据库驱动,JDBC(Java Database Connectivity)是 Java 应用程序访问数据库的标准 API(应用程序编程接口),数据库驱动的实现会将 JDBC 标准编程接口转换成对应数据库厂商的 SQL 实现。OceanBase 数据库 JDBC 驱动兼容 JDBC 4.0、4.1、4.2 标准。

JDBC 连接串的前置为 jdbc:oceanbase,其他使用和标准 JDBC 方式保持一致。样例代码:

  1. String url = "jdbc:oceanbase://host:port/SYS?useUnicode=true&characterEncoding=utf-8";
  2. String username = "SYS@oracle";
  3. String password = "";
  4. Connection conn = null;
  5. try {
  6. Class.forName("com.alipay.oceanbase.jdbc.Driver");
  7. conn = DriverManager.getConnection(url, username, password);
  8. PreparedStatement ps = conn.prepareStatement("select to_char(sysdate,'yyyy-MM-dd HH24:mi:ss') from dual;");
  9. ResultSet rs = ps.executeQuery();
  10. rs.next();
  11. System.out.println("sysdate is:" + rs.getString(1));
  12. rs.close();
  13. ps.close();
  14. } catch (Exception e) {
  15. e.printStackTrace();
  16. } finally {
  17. if (null != conn) {
  18. conn.close();
  19. }
  20. }