典型应用场景配置

日志诊断场景

ODBC日志分为unixODBC驱动管理器日志和psqlODBC驱动端日志。前者可以用于追溯应用程序API的执行是否成功,后者是底层实现过程中的一些DFX日志,用来帮助定位问题。

unixODBC日志需要在odbcinst.ini文件中配置:

  1. [ODBC]
  2. Trace=Yes
  3. TraceFile=/path/to/odbctrace.log
  4. [GaussMPP]
  5. Driver64=/usr/local/lib/psqlodbcw.so
  6. setup=/usr/local/lib/psqlodbcw.so

psqlODBC日志只需要在odbc.ini加上:

  1. [gaussdb]
  2. Driver=GaussMPP
  3. Servername=10.10.0.13(数据库Server IP
  4. ...
  5. Debug=1(打开驱动端debug日志)

典型应用场景配置 - 图1 说明: unixODBC日志将会生成在TraceFile配置的路径下,psqlODBC会在系统/tmp/下生成mylog_xxx.log。

高性能场景

进行大量数据插入时,建议如下:

  • 需要设置批量绑定:odbc.ini配置文件中设置UseBatchProtocol=1、数据库设置support_batch_bind=on。
  • ODBC程序绑定类型要和数据库中类型一致。
  • 客户端字符集和数据库字符集一致。
  • 事务改成手动提交。

odbc.ini配置文件:

  1. [gaussdb]
  2. Driver=GaussMPP
  3. Servername=10.10.0.13(数据库Server IP
  4. ...
  5. UseBatchProtocol=1 (默认打开)
  6. ConnSettings=set client_encoding=UTF8 (设置客户端字符编码,保证和server端一致)

绑定类型用例:

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <sql.h>
  4. #include <sqlext.h>
  5. #include <string.h>
  6. #include <sys/time.h>
  7. #define MESSAGE_BUFFER_LEN 128
  8. SQLHANDLE h_env = NULL;
  9. SQLHANDLE h_conn = NULL;
  10. SQLHANDLE h_stmt = NULL;
  11. void print_error()
  12. {
  13. SQLCHAR Sqlstate[SQL_SQLSTATE_SIZE+1];
  14. SQLINTEGER NativeError;
  15. SQLCHAR MessageText[MESSAGE_BUFFER_LEN];
  16. SQLSMALLINT TextLength;
  17. SQLRETURN ret = SQL_ERROR;
  18. ret = SQLGetDiagRec(SQL_HANDLE_STMT, h_stmt, 1, Sqlstate, &NativeError, MessageText, MESSAGE_BUFFER_LEN, &TextLength);
  19. if ( SQL_SUCCESS == ret)
  20. {
  21. printf("\n STMT ERROR-%05d %s", NativeError, MessageText);
  22. return;
  23. }
  24. ret = SQLGetDiagRec(SQL_HANDLE_DBC, h_conn, 1, Sqlstate, &NativeError, MessageText, MESSAGE_BUFFER_LEN, &TextLength);
  25. if ( SQL_SUCCESS == ret)
  26. {
  27. printf("\n CONN ERROR-%05d %s", NativeError, MessageText);
  28. return;
  29. }
  30. ret = SQLGetDiagRec(SQL_HANDLE_ENV, h_env, 1, Sqlstate, &NativeError, MessageText, MESSAGE_BUFFER_LEN, &TextLength);
  31. if ( SQL_SUCCESS == ret)
  32. {
  33. printf("\n ENV ERROR-%05d %s", NativeError, MessageText);
  34. return;
  35. }
  36. return;
  37. }
  38. /* 期盼函数返回SQL_SUCCESS */
  39. #define RETURN_IF_NOT_SUCCESS(func) \
  40. {\
  41. SQLRETURN ret_value = (func);\
  42. if (SQL_SUCCESS != ret_value)\
  43. {\
  44. print_error();\
  45. printf("\n failed line = %u: expect SQL_SUCCESS, but ret = %d", __LINE__, ret_value);\
  46. return SQL_ERROR; \
  47. }\
  48. }
  49. /* 期盼函数返回SQL_SUCCESS */
  50. #define RETURN_IF_NOT_SUCCESS_I(i, func) \
  51. {\
  52. SQLRETURN ret_value = (func);\
  53. if (SQL_SUCCESS != ret_value)\
  54. {\
  55. print_error();\
  56. printf("\n failed line = %u (i=%d): : expect SQL_SUCCESS, but ret = %d", __LINE__, (i), ret_value);\
  57. return SQL_ERROR; \
  58. }\
  59. }
  60. /* 期盼函数返回SQL_SUCCESS_WITH_INFO */
  61. #define RETURN_IF_NOT_SUCCESS_INFO(func) \
  62. {\
  63. SQLRETURN ret_value = (func);\
  64. if (SQL_SUCCESS_WITH_INFO != ret_value)\
  65. {\
  66. print_error();\
  67. printf("\n failed line = %u: expect SQL_SUCCESS_WITH_INFO, but ret = %d", __LINE__, ret_value);\
  68. return SQL_ERROR; \
  69. }\
  70. }
  71. /* 期盼数值相等 */
  72. #define RETURN_IF_NOT(expect, value) \
  73. if ((expect) != (value))\
  74. {\
  75. printf("\n failed line = %u: expect = %u, but value = %u", __LINE__, (expect), (value)); \
  76. return SQL_ERROR;\
  77. }
  78. /* 期盼字符串相同 */
  79. #define RETURN_IF_NOT_STRCMP_I(i, expect, value) \
  80. if (( NULL == (expect) ) || (NULL == (value)))\
  81. {\
  82. printf("\n failed line = %u (i=%u): input NULL pointer !", __LINE__, (i)); \
  83. return SQL_ERROR; \
  84. }\
  85. else if (0 != strcmp((expect), (value)))\
  86. {\
  87. printf("\n failed line = %u (i=%u): expect = %s, but value = %s", __LINE__, (i), (expect), (value)); \
  88. return SQL_ERROR;\
  89. }
  90. // prepare + execute SQL语句
  91. int execute_cmd(SQLCHAR *sql)
  92. {
  93. if ( NULL == sql )
  94. {
  95. return SQL_ERROR;
  96. }
  97. if ( SQL_SUCCESS != SQLPrepare(h_stmt, sql, SQL_NTS))
  98. {
  99. return SQL_ERROR;
  100. }
  101. if ( SQL_SUCCESS != SQLExecute(h_stmt))
  102. {
  103. return SQL_ERROR;
  104. }
  105. return SQL_SUCCESS;
  106. }
  107. // execute + commit 句柄
  108. int commit_exec()
  109. {
  110. if ( SQL_SUCCESS != SQLExecute(h_stmt))
  111. {
  112. return SQL_ERROR;
  113. }
  114. // 手动提交
  115. if ( SQL_SUCCESS != SQLEndTran(SQL_HANDLE_DBC, h_conn, SQL_COMMIT))
  116. {
  117. return SQL_ERROR;
  118. }
  119. return SQL_SUCCESS;
  120. }
  121. int begin_unit_test()
  122. {
  123. SQLINTEGER ret;
  124. /* 申请环境句柄 */
  125. ret = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &h_env);
  126. if ((SQL_SUCCESS != ret) && (SQL_SUCCESS_WITH_INFO != ret))
  127. {
  128. printf("\n begin_unit_test::SQLAllocHandle SQL_HANDLE_ENV failed ! ret = %d", ret);
  129. return SQL_ERROR;
  130. }
  131. /* 进行连接前必须要先设置版本号 */
  132. if (SQL_SUCCESS != SQLSetEnvAttr(h_env, SQL_ATTR_ODBC_VERSION, (SQLPOINTER)SQL_OV_ODBC3, 0))
  133. {
  134. print_error();
  135. printf("\n begin_unit_test::SQLSetEnvAttr SQL_ATTR_ODBC_VERSION failed ! ret = %d", ret);
  136. SQLFreeHandle(SQL_HANDLE_ENV, h_env);
  137. return SQL_ERROR;
  138. }
  139. /* 申请连接句柄 */
  140. ret = SQLAllocHandle(SQL_HANDLE_DBC, h_env, &h_conn);
  141. if (SQL_SUCCESS != ret)
  142. {
  143. print_error();
  144. printf("\n begin_unit_test::SQLAllocHandle SQL_HANDLE_DBC failed ! ret = %d", ret);
  145. SQLFreeHandle(SQL_HANDLE_ENV, h_env);
  146. return SQL_ERROR;
  147. }
  148. /* 建立连接 */
  149. ret = SQLConnect(h_conn, (SQLCHAR*) "gaussdb", SQL_NTS,
  150. (SQLCHAR*) NULL, 0, NULL, 0);
  151. if (SQL_SUCCESS != ret)
  152. {
  153. print_error();
  154. printf("\n begin_unit_test::SQLConnect failed ! ret = %d", ret);
  155. SQLFreeHandle(SQL_HANDLE_DBC, h_conn);
  156. SQLFreeHandle(SQL_HANDLE_ENV, h_env);
  157. return SQL_ERROR;
  158. }
  159. /* 申请语句句柄 */
  160. ret = SQLAllocHandle(SQL_HANDLE_STMT, h_conn, &h_stmt);
  161. if (SQL_SUCCESS != ret)
  162. {
  163. print_error();
  164. printf("\n begin_unit_test::SQLAllocHandle SQL_HANDLE_STMT failed ! ret = %d", ret);
  165. SQLFreeHandle(SQL_HANDLE_DBC, h_conn);
  166. SQLFreeHandle(SQL_HANDLE_ENV, h_env);
  167. return SQL_ERROR;
  168. }
  169. return SQL_SUCCESS;
  170. }
  171. void end_unit_test()
  172. {
  173. /* 释放语句句柄 */
  174. if (NULL != h_stmt)
  175. {
  176. SQLFreeHandle(SQL_HANDLE_STMT, h_stmt);
  177. }
  178. /* 释放连接句柄 */
  179. if (NULL != h_conn)
  180. {
  181. SQLDisconnect(h_conn);
  182. SQLFreeHandle(SQL_HANDLE_DBC, h_conn);
  183. }
  184. /* 释放环境句柄 */
  185. if (NULL != h_env)
  186. {
  187. SQLFreeHandle(SQL_HANDLE_ENV, h_env);
  188. }
  189. return;
  190. }
  191. int main()
  192. {
  193. // begin test
  194. if (begin_unit_test() != SQL_SUCCESS)
  195. {
  196. printf("\n begin_test_unit failed.");
  197. return SQL_ERROR;
  198. }
  199. // 句柄配置同前面用例
  200. int i = 0;
  201. SQLCHAR* sql_drop = "drop table if exists test_bindnumber_001";
  202. SQLCHAR* sql_create = "create table test_bindnumber_001("
  203. "f4 number, f5 number(10, 2)"
  204. ")";
  205. SQLCHAR* sql_insert = "insert into test_bindnumber_001 values(?, ?)";
  206. SQLCHAR* sql_select = "select * from test_bindnumber_001";
  207. SQLLEN RowCount;
  208. SQL_NUMERIC_STRUCT st_number;
  209. SQLCHAR getValue[2][MESSAGE_BUFFER_LEN];
  210. /* step 1. 建表 */
  211. RETURN_IF_NOT_SUCCESS(execute_cmd(sql_drop));
  212. RETURN_IF_NOT_SUCCESS(execute_cmd(sql_create));
  213. /* step 2.1 通过SQL_NUMERIC_STRUCT结构绑定参数 */
  214. RETURN_IF_NOT_SUCCESS(SQLPrepare(h_stmt, sql_insert, SQL_NTS));
  215. //第一行: 1234.5678
  216. memset(st_number.val, 0, SQL_MAX_NUMERIC_LEN);
  217. st_number.precision = 8;
  218. st_number.scale = 4;
  219. st_number.sign = 1;
  220. st_number.val[0] = 0x4E;
  221. st_number.val[1] = 0x61;
  222. st_number.val[2] = 0xBC;
  223. RETURN_IF_NOT_SUCCESS(SQLBindParameter(h_stmt, 1, SQL_PARAM_INPUT, SQL_C_NUMERIC, SQL_NUMERIC, sizeof(SQL_NUMERIC_STRUCT), 4, &st_number, 0, NULL));
  224. RETURN_IF_NOT_SUCCESS(SQLBindParameter(h_stmt, 2, SQL_PARAM_INPUT, SQL_C_NUMERIC, SQL_NUMERIC, sizeof(SQL_NUMERIC_STRUCT), 4, &st_number, 0, NULL));
  225. // 关闭自动提交
  226. SQLSetConnectAttr(h_conn, SQL_ATTR_AUTOCOMMIT, (SQLPOINTER)SQL_AUTOCOMMIT_OFF, 0);
  227. RETURN_IF_NOT_SUCCESS(commit_exec());
  228. RETURN_IF_NOT_SUCCESS(SQLRowCount(h_stmt, &RowCount));
  229. RETURN_IF_NOT(1, RowCount);
  230. //第二行: 12345678
  231. memset(st_number.val, 0, SQL_MAX_NUMERIC_LEN);
  232. st_number.precision = 8;
  233. st_number.scale = 0;
  234. st_number.sign = 1;
  235. st_number.val[0] = 0x4E;
  236. st_number.val[1] = 0x61;
  237. st_number.val[2] = 0xBC;
  238. RETURN_IF_NOT_SUCCESS(SQLBindParameter(h_stmt, 1, SQL_PARAM_INPUT, SQL_C_NUMERIC, SQL_NUMERIC, sizeof(SQL_NUMERIC_STRUCT), 0, &st_number, 0, NULL));
  239. RETURN_IF_NOT_SUCCESS(SQLBindParameter(h_stmt, 2, SQL_PARAM_INPUT, SQL_C_NUMERIC, SQL_NUMERIC, sizeof(SQL_NUMERIC_STRUCT), 0, &st_number, 0, NULL));
  240. RETURN_IF_NOT_SUCCESS(commit_exec());
  241. RETURN_IF_NOT_SUCCESS(SQLRowCount(h_stmt, &RowCount));
  242. RETURN_IF_NOT(1, RowCount);
  243. //第三行: 12345678
  244. memset(st_number.val, 0, SQL_MAX_NUMERIC_LEN);
  245. st_number.precision = 0;
  246. st_number.scale = 4;
  247. st_number.sign = 1;
  248. st_number.val[0] = 0x4E;
  249. st_number.val[1] = 0x61;
  250. st_number.val[2] = 0xBC;
  251. RETURN_IF_NOT_SUCCESS(SQLBindParameter(h_stmt, 1, SQL_PARAM_INPUT, SQL_C_NUMERIC, SQL_NUMERIC, sizeof(SQL_NUMERIC_STRUCT), 4, &st_number, 0, NULL));
  252. RETURN_IF_NOT_SUCCESS(SQLBindParameter(h_stmt, 2, SQL_PARAM_INPUT, SQL_C_NUMERIC, SQL_NUMERIC, sizeof(SQL_NUMERIC_STRUCT), 4, &st_number, 0, NULL));
  253. RETURN_IF_NOT_SUCCESS(commit_exec());
  254. RETURN_IF_NOT_SUCCESS(SQLRowCount(h_stmt, &RowCount));
  255. RETURN_IF_NOT(1, RowCount);
  256. /* step 2.2 第四行通过SQL_C_CHAR字符串绑定参数 */
  257. RETURN_IF_NOT_SUCCESS(SQLPrepare(h_stmt, sql_insert, SQL_NTS));
  258. SQLCHAR* szNumber = "1234.5678";
  259. RETURN_IF_NOT_SUCCESS(SQLBindParameter(h_stmt, 1, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_NUMERIC, strlen(szNumber), 0, szNumber, 0, NULL));
  260. RETURN_IF_NOT_SUCCESS(SQLBindParameter(h_stmt, 2, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_NUMERIC, strlen(szNumber), 0, szNumber, 0, NULL));
  261. RETURN_IF_NOT_SUCCESS(commit_exec());
  262. RETURN_IF_NOT_SUCCESS(SQLRowCount(h_stmt, &RowCount));
  263. RETURN_IF_NOT(1, RowCount);
  264. /* step 2.3 第五行通过SQL_C_FLOAT绑定参数 */
  265. RETURN_IF_NOT_SUCCESS(SQLPrepare(h_stmt, sql_insert, SQL_NTS));
  266. SQLREAL fNumber = 1234.5678;
  267. RETURN_IF_NOT_SUCCESS(SQLBindParameter(h_stmt, 1, SQL_PARAM_INPUT, SQL_C_FLOAT, SQL_NUMERIC, sizeof(fNumber), 4, &fNumber, 0, NULL));
  268. RETURN_IF_NOT_SUCCESS(SQLBindParameter(h_stmt, 2, SQL_PARAM_INPUT, SQL_C_FLOAT, SQL_NUMERIC, sizeof(fNumber), 4, &fNumber, 0, NULL));
  269. RETURN_IF_NOT_SUCCESS(commit_exec());
  270. RETURN_IF_NOT_SUCCESS(SQLRowCount(h_stmt, &RowCount));
  271. RETURN_IF_NOT(1, RowCount);
  272. /* step 2.4 第六行通过SQL_C_DOUBLE绑定参数 */
  273. RETURN_IF_NOT_SUCCESS(SQLPrepare(h_stmt, sql_insert, SQL_NTS));
  274. SQLDOUBLE dNumber = 1234.5678;
  275. RETURN_IF_NOT_SUCCESS(SQLBindParameter(h_stmt, 1, SQL_PARAM_INPUT, SQL_C_DOUBLE, SQL_NUMERIC, sizeof(dNumber), 4, &dNumber, 0, NULL));
  276. RETURN_IF_NOT_SUCCESS(SQLBindParameter(h_stmt, 2, SQL_PARAM_INPUT, SQL_C_DOUBLE, SQL_NUMERIC, sizeof(dNumber), 4, &dNumber, 0, NULL));
  277. RETURN_IF_NOT_SUCCESS(commit_exec());
  278. RETURN_IF_NOT_SUCCESS(SQLRowCount(h_stmt, &RowCount));
  279. RETURN_IF_NOT(1, RowCount);
  280. SQLBIGINT bNumber1 = 0xFFFFFFFFFFFFFFFF;
  281. SQLBIGINT bNumber2 = 12345;
  282. /* step 2.5 第七行通过SQL_C_SBIGINT绑定参数 */
  283. RETURN_IF_NOT_SUCCESS(SQLPrepare(h_stmt, sql_insert, SQL_NTS));
  284. RETURN_IF_NOT_SUCCESS(SQLBindParameter(h_stmt, 1, SQL_PARAM_INPUT, SQL_C_SBIGINT, SQL_NUMERIC, sizeof(bNumber1), 4, &bNumber1, 0, NULL));
  285. RETURN_IF_NOT_SUCCESS(SQLBindParameter(h_stmt, 2, SQL_PARAM_INPUT, SQL_C_SBIGINT, SQL_NUMERIC, sizeof(bNumber2), 4, &bNumber2, 0, NULL));
  286. RETURN_IF_NOT_SUCCESS(commit_exec());
  287. RETURN_IF_NOT_SUCCESS(SQLRowCount(h_stmt, &RowCount));
  288. RETURN_IF_NOT(1, RowCount);
  289. /* step 2.6 第八行通过SQL_C_UBIGINT绑定参数 */
  290. RETURN_IF_NOT_SUCCESS(SQLPrepare(h_stmt, sql_insert, SQL_NTS));
  291. RETURN_IF_NOT_SUCCESS(SQLBindParameter(h_stmt, 1, SQL_PARAM_INPUT, SQL_C_UBIGINT, SQL_NUMERIC, sizeof(bNumber1), 4, &bNumber1, 0, NULL));
  292. RETURN_IF_NOT_SUCCESS(SQLBindParameter(h_stmt, 2, SQL_PARAM_INPUT, SQL_C_UBIGINT, SQL_NUMERIC, sizeof(bNumber2), 4, &bNumber2, 0, NULL));
  293. RETURN_IF_NOT_SUCCESS(commit_exec());
  294. RETURN_IF_NOT_SUCCESS(SQLRowCount(h_stmt, &RowCount));
  295. RETURN_IF_NOT(1, RowCount);
  296. SQLLEN lNumber1 = 0xFFFFFFFFFFFFFFFF;
  297. SQLLEN lNumber2 = 12345;
  298. /* step 2.7 第九行通过SQL_C_LONG绑定参数 */
  299. RETURN_IF_NOT_SUCCESS(SQLPrepare(h_stmt, sql_insert, SQL_NTS));
  300. RETURN_IF_NOT_SUCCESS(SQLBindParameter(h_stmt, 1, SQL_PARAM_INPUT, SQL_C_LONG, SQL_NUMERIC, sizeof(lNumber1), 0, &lNumber1, 0, NULL));
  301. RETURN_IF_NOT_SUCCESS(SQLBindParameter(h_stmt, 2, SQL_PARAM_INPUT, SQL_C_LONG, SQL_NUMERIC, sizeof(lNumber2), 0, &lNumber2, 0, NULL));
  302. RETURN_IF_NOT_SUCCESS(commit_exec());
  303. RETURN_IF_NOT_SUCCESS(SQLRowCount(h_stmt, &RowCount));
  304. RETURN_IF_NOT(1, RowCount);
  305. /* step 2.8 第十行通过SQL_C_ULONG绑定参数 */
  306. RETURN_IF_NOT_SUCCESS(SQLPrepare(h_stmt, sql_insert, SQL_NTS));
  307. RETURN_IF_NOT_SUCCESS(SQLBindParameter(h_stmt, 1, SQL_PARAM_INPUT, SQL_C_ULONG, SQL_NUMERIC, sizeof(lNumber1), 0, &lNumber1, 0, NULL));
  308. RETURN_IF_NOT_SUCCESS(SQLBindParameter(h_stmt, 2, SQL_PARAM_INPUT, SQL_C_ULONG, SQL_NUMERIC, sizeof(lNumber2), 0, &lNumber2, 0, NULL));
  309. RETURN_IF_NOT_SUCCESS(commit_exec());
  310. RETURN_IF_NOT_SUCCESS(SQLRowCount(h_stmt, &RowCount));
  311. RETURN_IF_NOT(1, RowCount);
  312. SQLSMALLINT sNumber = 0xFFFF;
  313. /* step 2.9 第十一行通过SQL_C_SHORT绑定参数 */
  314. RETURN_IF_NOT_SUCCESS(SQLPrepare(h_stmt, sql_insert, SQL_NTS));
  315. RETURN_IF_NOT_SUCCESS(SQLBindParameter(h_stmt, 1, SQL_PARAM_INPUT, SQL_C_SHORT, SQL_NUMERIC, sizeof(sNumber), 0, &sNumber, 0, NULL));
  316. RETURN_IF_NOT_SUCCESS(SQLBindParameter(h_stmt, 2, SQL_PARAM_INPUT, SQL_C_SHORT, SQL_NUMERIC, sizeof(sNumber), 0, &sNumber, 0, NULL));
  317. RETURN_IF_NOT_SUCCESS(commit_exec());
  318. RETURN_IF_NOT_SUCCESS(SQLRowCount(h_stmt, &RowCount));
  319. RETURN_IF_NOT(1, RowCount);
  320. /* step 2.10 第十二行通过SQL_C_USHORT绑定参数 */
  321. RETURN_IF_NOT_SUCCESS(SQLPrepare(h_stmt, sql_insert, SQL_NTS));
  322. RETURN_IF_NOT_SUCCESS(SQLBindParameter(h_stmt, 1, SQL_PARAM_INPUT, SQL_C_USHORT, SQL_NUMERIC, sizeof(sNumber), 0, &sNumber, 0, NULL));
  323. RETURN_IF_NOT_SUCCESS(SQLBindParameter(h_stmt, 2, SQL_PARAM_INPUT, SQL_C_USHORT, SQL_NUMERIC, sizeof(sNumber), 0, &sNumber, 0, NULL));
  324. RETURN_IF_NOT_SUCCESS(commit_exec());
  325. RETURN_IF_NOT_SUCCESS(SQLRowCount(h_stmt, &RowCount));
  326. RETURN_IF_NOT(1, RowCount);
  327. SQLCHAR cNumber = 0xFF;
  328. /* step 2.11 第十三行通过SQL_C_TINYINT绑定参数 */
  329. RETURN_IF_NOT_SUCCESS(SQLPrepare(h_stmt, sql_insert, SQL_NTS));
  330. RETURN_IF_NOT_SUCCESS(SQLBindParameter(h_stmt, 1, SQL_PARAM_INPUT, SQL_C_TINYINT, SQL_NUMERIC, sizeof(cNumber), 0, &cNumber, 0, NULL));
  331. RETURN_IF_NOT_SUCCESS(SQLBindParameter(h_stmt, 2, SQL_PARAM_INPUT, SQL_C_TINYINT, SQL_NUMERIC, sizeof(cNumber), 0, &cNumber, 0, NULL));
  332. RETURN_IF_NOT_SUCCESS(commit_exec());
  333. RETURN_IF_NOT_SUCCESS(SQLRowCount(h_stmt, &RowCount));
  334. RETURN_IF_NOT(1, RowCount);
  335. /* step 2.12 第十四行通过SQL_C_UTINYINT绑定参数 */
  336. RETURN_IF_NOT_SUCCESS(SQLPrepare(h_stmt, sql_insert, SQL_NTS));
  337. RETURN_IF_NOT_SUCCESS(SQLBindParameter(h_stmt, 1, SQL_PARAM_INPUT, SQL_C_UTINYINT, SQL_NUMERIC, sizeof(cNumber), 0, &cNumber, 0, NULL));
  338. RETURN_IF_NOT_SUCCESS(SQLBindParameter(h_stmt, 2, SQL_PARAM_INPUT, SQL_C_UTINYINT, SQL_NUMERIC, sizeof(cNumber), 0, &cNumber, 0, NULL));
  339. RETURN_IF_NOT_SUCCESS(commit_exec());
  340. RETURN_IF_NOT_SUCCESS(SQLRowCount(h_stmt, &RowCount));
  341. RETURN_IF_NOT(1, RowCount);
  342. /* 用字符串类型统一进行期盼 */
  343. SQLCHAR* expectValue[14][2] = {{"1234.5678", "1234.57"},
  344. {"12345678", "12345678"},
  345. {"0", "0"},
  346. {"1234.5678", "1234.57"},
  347. {"1234.5677", "1234.57"},
  348. {"1234.5678", "1234.57"},
  349. {"-1", "12345"},
  350. {"18446744073709551615", "12345"},
  351. {"-1", "12345"},
  352. {"4294967295", "12345"},
  353. {"-1", "-1"},
  354. {"65535", "65535"},
  355. {"-1", "-1"},
  356. {"255", "255"},
  357. };
  358. RETURN_IF_NOT_SUCCESS(execute_cmd(sql_select));
  359. while ( SQL_NO_DATA != SQLFetch(h_stmt))
  360. {
  361. RETURN_IF_NOT_SUCCESS_I(i, SQLGetData(h_stmt, 1, SQL_C_CHAR, &getValue[0], MESSAGE_BUFFER_LEN, NULL));
  362. RETURN_IF_NOT_SUCCESS_I(i, SQLGetData(h_stmt, 2, SQL_C_CHAR, &getValue[1], MESSAGE_BUFFER_LEN, NULL));
  363. //RETURN_IF_NOT_STRCMP_I(i, expectValue[i][0], getValue[0]);
  364. //RETURN_IF_NOT_STRCMP_I(i, expectValue[i][1], getValue[1]);
  365. i++;
  366. }
  367. RETURN_IF_NOT_SUCCESS(SQLRowCount(h_stmt, &RowCount));
  368. RETURN_IF_NOT(i, RowCount);
  369. SQLCloseCursor(h_stmt);
  370. /* step final. 删除表还原环境 */
  371. RETURN_IF_NOT_SUCCESS(execute_cmd(sql_drop));
  372. end_unit_test();
  373. }

典型应用场景配置 - 图2 说明: 上述用例中定义了number列,调用SQLBindParameter接口时,绑定SQL_NUMERIC会比SQL_LONG性能高一些。因为如果是char,在数据库服务端插入数据时需要进行数据类型转换,从而引发性能瓶颈。