示例:常用功能和批量绑定

常用功能示例代码

  1. // 此示例演示如何通过ODBC方式获取openGauss中的数据。
  2. // DBtest.c (compile with: libodbc.so)
  3. #include <stdlib.h>
  4. #include <stdio.h>
  5. #include <sqlext.h>
  6. #ifdef WIN32
  7. #include <windows.h>
  8. #endif
  9. SQLHENV V_OD_Env; // Handle ODBC environment
  10. SQLHSTMT V_OD_hstmt; // Handle statement
  11. SQLHDBC V_OD_hdbc; // Handle connection
  12. char typename[100];
  13. SQLINTEGER value = 100;
  14. SQLINTEGER V_OD_erg,V_OD_buffer,V_OD_err,V_OD_id;
  15. int main(int argc,char *argv[])
  16. {
  17. // 1. 申请环境句柄
  18. V_OD_erg = SQLAllocHandle(SQL_HANDLE_ENV,SQL_NULL_HANDLE,&V_OD_Env);
  19. if ((V_OD_erg != SQL_SUCCESS) && (V_OD_erg != SQL_SUCCESS_WITH_INFO))
  20. {
  21. printf("Error AllocHandle\n");
  22. exit(0);
  23. }
  24. // 2. 设置环境属性(版本信息)
  25. SQLSetEnvAttr(V_OD_Env, SQL_ATTR_ODBC_VERSION, (void*)SQL_OV_ODBC3, 0);
  26. // 3. 申请连接句柄
  27. V_OD_erg = SQLAllocHandle(SQL_HANDLE_DBC, V_OD_Env, &V_OD_hdbc);
  28. if ((V_OD_erg != SQL_SUCCESS) && (V_OD_erg != SQL_SUCCESS_WITH_INFO))
  29. {
  30. SQLFreeHandle(SQL_HANDLE_ENV, V_OD_Env);
  31. exit(0);
  32. }
  33. // 4. 设置连接属性
  34. SQLSetConnectAttr(V_OD_hdbc, SQL_ATTR_AUTOCOMMIT, SQL_AUTOCOMMIT_ON, 0);
  35. // 5. 连接数据源,这里的“userName”与“password”分别表示连接数据库的用户名和用户密码,请根据实际情况修改。
  36. // 如果odbc.ini文件中已经配置了用户名密码,那么这里可以留空("");但是不建议这么做,因为一旦odbc.ini权限管理不善,将导致数据库用户密码泄露。
  37. V_OD_erg = SQLConnect(V_OD_hdbc, (SQLCHAR*) "gaussdb", SQL_NTS,
  38. (SQLCHAR*) "userName", SQL_NTS, (SQLCHAR*) "password", SQL_NTS);
  39. if ((V_OD_erg != SQL_SUCCESS) && (V_OD_erg != SQL_SUCCESS_WITH_INFO))
  40. {
  41. printf("Error SQLConnect %d\n",V_OD_erg);
  42. SQLFreeHandle(SQL_HANDLE_ENV, V_OD_Env);
  43. exit(0);
  44. }
  45. printf("Connected !\n");
  46. // 6. 设置语句属性
  47. SQLSetStmtAttr(V_OD_hstmt,SQL_ATTR_QUERY_TIMEOUT,(SQLPOINTER *)3,0);
  48. // 7. 申请语句句柄
  49. SQLAllocHandle(SQL_HANDLE_STMT, V_OD_hdbc, &V_OD_hstmt);
  50. // 8. 直接执行SQL语句。
  51. SQLExecDirect(V_OD_hstmt,"drop table IF EXISTS customer_t1",SQL_NTS);
  52. SQLExecDirect(V_OD_hstmt,"CREATE TABLE customer_t1(c_customer_sk INTEGER, c_customer_name VARCHAR(32));",SQL_NTS);
  53. SQLExecDirect(V_OD_hstmt,"insert into customer_t1 values(25,li)",SQL_NTS);
  54. // 9. 准备执行
  55. SQLPrepare(V_OD_hstmt,"insert into customer_t1 values(?)",SQL_NTS);
  56. // 10. 绑定参数
  57. SQLBindParameter(V_OD_hstmt,1,SQL_PARAM_INPUT,SQL_C_SLONG,SQL_INTEGER,0,0,
  58. &value,0,NULL);
  59. // 11. 执行准备好的语句
  60. SQLExecute(V_OD_hstmt);
  61. SQLExecDirect(V_OD_hstmt,"select id from testtable",SQL_NTS);
  62. // 12. 获取结果集某一列的属性
  63. SQLColAttribute(V_OD_hstmt,1,SQL_DESC_TYPE,typename,100,NULL,NULL);
  64. printf("SQLColAtrribute %s\n",typename);
  65. // 13. 绑定结果集
  66. SQLBindCol(V_OD_hstmt,1,SQL_C_SLONG, (SQLPOINTER)&V_OD_buffer,150,
  67. (SQLLEN *)&V_OD_err);
  68. // 14. 通过SQLFetch取结果集中数据
  69. V_OD_erg=SQLFetch(V_OD_hstmt);
  70. // 15. 通过SQLGetData获取并返回数据。
  71. while(V_OD_erg != SQL_NO_DATA)
  72. {
  73. SQLGetData(V_OD_hstmt,1,SQL_C_SLONG,(SQLPOINTER)&V_OD_id,0,NULL);
  74. printf("SQLGetData ----ID = %d\n",V_OD_id);
  75. V_OD_erg=SQLFetch(V_OD_hstmt);
  76. };
  77. printf("Done !\n");
  78. // 16. 断开数据源连接并释放句柄资源
  79. SQLFreeHandle(SQL_HANDLE_STMT,V_OD_hstmt);
  80. SQLDisconnect(V_OD_hdbc);
  81. SQLFreeHandle(SQL_HANDLE_DBC,V_OD_hdbc);
  82. SQLFreeHandle(SQL_HANDLE_ENV, V_OD_Env);
  83. return(0);
  84. }

批量绑定示例代码

  1. /**********************************************************************
  2. * 请在数据源中打开UseBatchProtocol,同时指定数据库中参数support_batch_bind
  3. * 为on
  4. * CHECK_ERROR的作用是检查并打印错误信息。
  5. * 此示例将与用户交互式获取DSN、模拟的数据量,忽略的数据量,并将最终数据入库到test_odbc_batch_insert中
  6. ***********************************************************************/
  7. #include <stdio.h>
  8. #include <stdlib.h>
  9. #include <sql.h>
  10. #include <sqlext.h>
  11. #include <string.h>
  12. void Exec(SQLHDBC hdbc, SQLCHAR* sql)
  13. {
  14. SQLRETURN retcode; // Return status
  15. SQLHSTMT hstmt = SQL_NULL_HSTMT; // Statement handle
  16. SQLCHAR loginfo[2048];
  17. // Allocate Statement Handle
  18. retcode = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt);
  19. if (!SQL_SUCCEEDED(retcode)) {
  20. printf("SQLAllocHandle(SQL_HANDLE_STMT) failed");
  21. return;
  22. }
  23. // Prepare Statement
  24. retcode = SQLPrepare(hstmt, (SQLCHAR*) sql, SQL_NTS);
  25. sprintf((char*)loginfo, "SQLPrepare log: %s", (char*)sql);
  26. if (!SQL_SUCCEEDED(retcode)) {
  27. printf("SQLPrepare(hstmt, (SQLCHAR*) sql, SQL_NTS) failed");
  28. return;
  29. }
  30. // Execute Statement
  31. retcode = SQLExecute(hstmt);
  32. sprintf((char*)loginfo, "SQLExecute stmt log: %s", (char*)sql);
  33. if (!SQL_SUCCEEDED(retcode)) {
  34. printf("SQLExecute(hstmt) failed");
  35. return;
  36. }
  37. // Free Handle
  38. retcode = SQLFreeHandle(SQL_HANDLE_STMT, hstmt);
  39. sprintf((char*)loginfo, "SQLFreeHandle stmt log: %s", (char*)sql);
  40. if (!SQL_SUCCEEDED(retcode)) {
  41. printf("SQLFreeHandle(SQL_HANDLE_STMT, hstmt) failed");
  42. return;
  43. }
  44. }
  45. int main ()
  46. {
  47. SQLHENV henv = SQL_NULL_HENV;
  48. SQLHDBC hdbc = SQL_NULL_HDBC;
  49. int batchCount = 1000; // 批量绑定的数据量
  50. SQLLEN rowsCount = 0;
  51. int ignoreCount = 0; // 批量绑定的数据中,不要入库的数据量
  52. SQLRETURN retcode;
  53. SQLCHAR dsn[1024] = {'\0'};
  54. SQLCHAR loginfo[2048];
  55. do
  56. {
  57. if (ignoreCount > batchCount)
  58. {
  59. printf("ignoreCount(%d) should be less than batchCount(%d)\n", ignoreCount, batchCount);
  60. }
  61. }while(ignoreCount > batchCount);
  62. retcode = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv);
  63. if (!SQL_SUCCEEDED(retcode)) {
  64. printf("SQLAllocHandle failed");
  65. goto exit;
  66. }
  67. // Set ODBC Verion
  68. retcode = SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION,
  69. (SQLPOINTER*)SQL_OV_ODBC3, 0);
  70. if (!SQL_SUCCEEDED(retcode)) {
  71. printf("SQLSetEnvAttr failed");
  72. goto exit;
  73. }
  74. // Allocate Connection
  75. retcode = SQLAllocHandle(SQL_HANDLE_DBC, henv, &hdbc);
  76. if (!SQL_SUCCEEDED(retcode)) {
  77. printf("SQLAllocHandle failed");
  78. goto exit;
  79. }
  80. // Set Login Timeout
  81. retcode = SQLSetConnectAttr(hdbc, SQL_LOGIN_TIMEOUT, (SQLPOINTER)5, 0);
  82. if (!SQL_SUCCEEDED(retcode)) {
  83. printf("SQLSetConnectAttr failed");
  84. goto exit;
  85. }
  86. // Set Auto Commit
  87. retcode = SQLSetConnectAttr(hdbc, SQL_ATTR_AUTOCOMMIT,
  88. (SQLPOINTER)(1), 0);
  89. if (!SQL_SUCCEEDED(retcode)) {
  90. printf("SQLSetConnectAttr failed");
  91. goto exit;
  92. }
  93. // Connect to DSN
  94. // gaussdb替换成用户所使用的数据源名称
  95. sprintf(loginfo, "SQLConnect(DSN:%s)", dsn);
  96. retcode = SQLConnect(hdbc, (SQLCHAR*) "gaussdb", SQL_NTS,
  97. (SQLCHAR*) NULL, 0, NULL, 0);
  98. if (!SQL_SUCCEEDED(retcode)) {
  99. printf("SQLConnect failed");
  100. goto exit;
  101. }
  102. // init table info.
  103. Exec(hdbc, "drop table if exists test_odbc_batch_insert");
  104. Exec(hdbc, "create table test_odbc_batch_insert(id int primary key, col varchar2(50))");
  105. // 下面的代码根据用户输入的数据量,构造出将要入库的数据:
  106. {
  107. SQLRETURN retcode;
  108. SQLHSTMT hstmtinesrt = SQL_NULL_HSTMT;
  109. int i;
  110. SQLCHAR *sql = NULL;
  111. SQLINTEGER *ids = NULL;
  112. SQLCHAR *cols = NULL;
  113. SQLLEN *bufLenIds = NULL;
  114. SQLLEN *bufLenCols = NULL;
  115. SQLUSMALLINT *operptr = NULL;
  116. SQLUSMALLINT *statusptr = NULL;
  117. SQLULEN process = 0;
  118. // 这里是按列构造,每个字段的内存连续存放在一起。
  119. ids = (SQLINTEGER*)malloc(sizeof(ids[0]) * batchCount);
  120. cols = (SQLCHAR*)malloc(sizeof(cols[0]) * batchCount * 50);
  121. // 这里是每个字段中,每一行数据的内存长度。
  122. bufLenIds = (SQLLEN*)malloc(sizeof(bufLenIds[0]) * batchCount);
  123. bufLenCols = (SQLLEN*)malloc(sizeof(bufLenCols[0]) * batchCount);
  124. // 该行是否需要被处理,SQL_PARAM_IGNORE 或 SQL_PARAM_PROCEED
  125. operptr = (SQLUSMALLINT*)malloc(sizeof(operptr[0]) * batchCount);
  126. memset(operptr, 0, sizeof(operptr[0]) * batchCount);
  127. // 该行的处理结果。
  128. // 注:由于数据库中处理方式是同一语句隶属同一事务中,所以如果出错,那么待处理数据都将是出错的,并不会部分入库。
  129. statusptr = (SQLUSMALLINT*)malloc(sizeof(statusptr[0]) * batchCount);
  130. memset(statusptr, 88, sizeof(statusptr[0]) * batchCount);
  131. if (NULL == ids || NULL == cols || NULL == bufLenCols || NULL == bufLenIds)
  132. {
  133. fprintf(stderr, "FAILED:\tmalloc data memory failed\n");
  134. goto exit;
  135. }
  136. for (int i = 0; i < batchCount; i++)
  137. {
  138. ids[i] = i;
  139. sprintf(cols + 50 * i, "column test value %d", i);
  140. bufLenIds[i] = sizeof(ids[i]);
  141. bufLenCols[i] = strlen(cols + 50 * i);
  142. operptr[i] = (i < ignoreCount) ? SQL_PARAM_IGNORE : SQL_PARAM_PROCEED;
  143. }
  144. // Allocate Statement Handle
  145. retcode = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmtinesrt);
  146. if (!SQL_SUCCEEDED(retcode)) {
  147. printf("SQLAllocHandle failed");
  148. goto exit;
  149. }
  150. // Prepare Statement
  151. sql = (SQLCHAR*)"insert into test_odbc_batch_insert values(?, ?)";
  152. retcode = SQLPrepare(hstmtinesrt, (SQLCHAR*) sql, SQL_NTS);
  153. sprintf((char*)loginfo, "SQLPrepare log: %s", (char*)sql);
  154. if (!SQL_SUCCEEDED(retcode)) {
  155. printf("SQLPrepare failed");
  156. goto exit;
  157. }
  158. retcode = SQLSetStmtAttr(hstmtinesrt, SQL_ATTR_PARAMSET_SIZE, (SQLPOINTER)batchCount, sizeof(batchCount));
  159. if (!SQL_SUCCEEDED(retcode)) {
  160. printf("SQLSetStmtAttr failed");
  161. goto exit;
  162. }
  163. retcode = SQLBindParameter(hstmtinesrt, 1, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, sizeof(ids[0]), 0,&(ids[0]), 0, bufLenIds);
  164. if (!SQL_SUCCEEDED(retcode)) {
  165. printf("SQLBindParameter failed");
  166. goto exit;
  167. }
  168. retcode = SQLBindParameter(hstmtinesrt, 2, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, 50, 50, cols, 50, bufLenCols);
  169. if (!SQL_SUCCEEDED(retcode)) {
  170. printf("SQLBindParameter failed");
  171. goto exit;
  172. }
  173. retcode = SQLSetStmtAttr(hstmtinesrt, SQL_ATTR_PARAMS_PROCESSED_PTR, (SQLPOINTER)&process, sizeof(process));
  174. if (!SQL_SUCCEEDED(retcode)) {
  175. printf("SQLSetStmtAttr failed");
  176. goto exit;
  177. }
  178. retcode = SQLSetStmtAttr(hstmtinesrt, SQL_ATTR_PARAM_STATUS_PTR, (SQLPOINTER)statusptr, sizeof(statusptr[0]) * batchCount);
  179. if (!SQL_SUCCEEDED(retcode)) {
  180. printf("SQLSetStmtAttr failed");
  181. goto exit;
  182. }
  183. retcode = SQLSetStmtAttr(hstmtinesrt, SQL_ATTR_PARAM_OPERATION_PTR, (SQLPOINTER)operptr, sizeof(operptr[0]) * batchCount);
  184. if (!SQL_SUCCEEDED(retcode)) {
  185. printf("SQLSetStmtAttr failed");
  186. goto exit;
  187. }
  188. retcode = SQLExecute(hstmtinesrt);
  189. sprintf((char*)loginfo, "SQLExecute stmt log: %s", (char*)sql);
  190. if (!SQL_SUCCEEDED(retcode)) {
  191. printf("SQLExecute(hstmtinesrt) failed");
  192. goto exit;
  193. retcode = SQLRowCount(hstmtinesrt, &rowsCount);
  194. if (!SQL_SUCCEEDED(retcode)) {
  195. printf("SQLRowCount failed");
  196. goto exit;
  197. }
  198. if (rowsCount != (batchCount - ignoreCount))
  199. {
  200. sprintf(loginfo, "(batchCount - ignoreCount)(%d) != rowsCount(%d)", (batchCount - ignoreCount), rowsCount);
  201. if (!SQL_SUCCEEDED(retcode)) {
  202. printf("SQLExecute failed");
  203. goto exit;
  204. }
  205. }
  206. else
  207. {
  208. sprintf(loginfo, "(batchCount - ignoreCount)(%d) == rowsCount(%d)", (batchCount - ignoreCount), rowsCount);
  209. if (!SQL_SUCCEEDED(retcode)) {
  210. printf("SQLExecute failed");
  211. goto exit;
  212. }
  213. }
  214. // check row number returned
  215. if (rowsCount != process)
  216. {
  217. sprintf(loginfo, "process(%d) != rowsCount(%d)", process, rowsCount);
  218. if (!SQL_SUCCEEDED(retcode)) {
  219. printf("SQLExecute failed");
  220. goto exit;
  221. }
  222. }
  223. else
  224. {
  225. sprintf(loginfo, "process(%d) == rowsCount(%d)", process, rowsCount);
  226. if (!SQL_SUCCEEDED(retcode)) {
  227. printf("SQLExecute failed");
  228. goto exit;
  229. }
  230. }
  231. for (int i = 0; i < batchCount; i++)
  232. {
  233. if (i < ignoreCount)
  234. {
  235. if (statusptr[i] != SQL_PARAM_UNUSED)
  236. {
  237. sprintf(loginfo, "statusptr[%d](%d) != SQL_PARAM_UNUSED", i, statusptr[i]);
  238. if (!SQL_SUCCEEDED(retcode)) {
  239. printf("SQLExecute failed");
  240. goto exit;
  241. }
  242. }
  243. }
  244. else if (statusptr[i] != SQL_PARAM_SUCCESS)
  245. {
  246. sprintf(loginfo, "statusptr[%d](%d) != SQL_PARAM_SUCCESS", i, statusptr[i]);
  247. if (!SQL_SUCCEEDED(retcode)) {
  248. printf("SQLExecute failed");
  249. goto exit;
  250. }
  251. }
  252. }
  253. retcode = SQLFreeHandle(SQL_HANDLE_STMT, hstmtinesrt);
  254. sprintf((char*)loginfo, "SQLFreeHandle hstmtinesrt");
  255. if (!SQL_SUCCEEDED(retcode)) {
  256. printf("SQLFreeHandle failed");
  257. goto exit;
  258. }
  259. }
  260. exit:
  261. (void) printf ("\nComplete.\n");
  262. // Connection
  263. if (hdbc != SQL_NULL_HDBC) {
  264. SQLDisconnect(hdbc);
  265. SQLFreeHandle(SQL_HANDLE_DBC, hdbc);
  266. }
  267. // Environment
  268. if (henv != SQL_NULL_HENV)
  269. SQLFreeHandle(SQL_HANDLE_ENV, henv);
  270. return 0;
  271. }