典型应用场景配置

日志诊断场景

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

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

1. [ODBC]
2. Trace=Yes
3. TraceFile=/path/to/odbctrace.log

5. [GaussMPP]
6. Driver64=/usr/local/lib/psqlodbcw.so
7. 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>

8. #define MESSAGE_BUFFER_LEN  128
9. SQLHANDLE   h_env = NULL;
10. SQLHANDLE   h_conn = NULL;
11. SQLHANDLE   h_stmt = NULL;
12. void print_error()
13. {
14. SQLCHAR     Sqlstate[SQL_SQLSTATE_SIZE+1];
15. SQLINTEGER  NativeError;
16. SQLCHAR     MessageText[MESSAGE_BUFFER_LEN];
17. SQLSMALLINT TextLength;
18. SQLRETURN   ret = SQL_ERROR;

20. ret = SQLGetDiagRec(SQL_HANDLE_STMT, h_stmt, 1, Sqlstate, &NativeError, MessageText, MESSAGE_BUFFER_LEN, &TextLength);
21. if ( SQL_SUCCESS == ret)
22. {
23. printf("\n STMT ERROR-%05d %s", NativeError, MessageText);
24. return;
25. }

27. ret = SQLGetDiagRec(SQL_HANDLE_DBC, h_conn, 1, Sqlstate, &NativeError, MessageText, MESSAGE_BUFFER_LEN, &TextLength);
28. if ( SQL_SUCCESS == ret)
29. {
30. printf("\n CONN ERROR-%05d %s", NativeError, MessageText);
31. return;
32. }

34. ret = SQLGetDiagRec(SQL_HANDLE_ENV, h_env, 1, Sqlstate, &NativeError, MessageText, MESSAGE_BUFFER_LEN, &TextLength);
35. if ( SQL_SUCCESS == ret)
36. {
37. printf("\n ENV ERROR-%05d %s", NativeError, MessageText);
38. return;
39. }

41. return;
42. }

44. /* 期盼函数返回SQL_SUCCESS */
45. #define RETURN_IF_NOT_SUCCESS(func) \
46. {\
47. SQLRETURN ret_value = (func);\
48. if (SQL_SUCCESS != ret_value)\
49. {\
50. print_error();\
51. printf("\n failed line = %u: expect SQL_SUCCESS, but ret = %d", __LINE__, ret_value);\
52. return SQL_ERROR; \
53. }\
54. }

56. /* 期盼函数返回SQL_SUCCESS */
57. #define RETURN_IF_NOT_SUCCESS_I(i, func) \
58. {\
59. SQLRETURN ret_value = (func);\
60. if (SQL_SUCCESS != ret_value)\
61. {\
62. print_error();\
63. printf("\n failed line = %u (i=%d): : expect SQL_SUCCESS, but ret = %d", __LINE__, (i), ret_value);\
64. return SQL_ERROR; \
65. }\
66. }

68. /* 期盼函数返回SQL_SUCCESS_WITH_INFO */
69. #define RETURN_IF_NOT_SUCCESS_INFO(func) \
70. {\
71. SQLRETURN ret_value = (func);\
72. if (SQL_SUCCESS_WITH_INFO != ret_value)\
73. {\
74. print_error();\
75. printf("\n failed line = %u: expect SQL_SUCCESS_WITH_INFO, but ret = %d", __LINE__, ret_value);\
76. return SQL_ERROR; \
77. }\
78. }

80. /* 期盼数值相等 */
81. #define RETURN_IF_NOT(expect, value) \
82. if ((expect) != (value))\
83. {\
84. printf("\n failed line = %u: expect = %u, but value = %u", __LINE__, (expect), (value)); \
85. return SQL_ERROR;\
86. }

88. /* 期盼字符串相同 */
89. #define RETURN_IF_NOT_STRCMP_I(i, expect, value) \
90. if (( NULL == (expect) ) || (NULL == (value)))\
91. {\
92. printf("\n failed line = %u (i=%u): input NULL pointer !", __LINE__, (i)); \
93. return SQL_ERROR; \
94. }\
95. else if (0 != strcmp((expect), (value)))\
96. {\
97. printf("\n failed line = %u (i=%u): expect = %s, but value = %s", __LINE__, (i), (expect), (value)); \
98. return SQL_ERROR;\
99. }

102. // prepare + execute SQL语句
103. int execute_cmd(SQLCHAR *sql)
104. {
105. if ( NULL == sql )
106. {
107. return SQL_ERROR;
108. }

110. if ( SQL_SUCCESS != SQLPrepare(h_stmt, sql, SQL_NTS))
111. {
112. return SQL_ERROR;
113. }

115. if ( SQL_SUCCESS != SQLExecute(h_stmt))
116. {
117. return SQL_ERROR;
118. }

120. return SQL_SUCCESS;
121. }
122. // execute + commit 句柄
123. int commit_exec()
124. {
125. if ( SQL_SUCCESS != SQLExecute(h_stmt))
126. {
127. return SQL_ERROR;
128. }

130. // 手动提交
131. if ( SQL_SUCCESS != SQLEndTran(SQL_HANDLE_DBC, h_conn, SQL_COMMIT))
132. {
133. return SQL_ERROR;
134. }

136. return SQL_SUCCESS;
137. }

139. int begin_unit_test()
140. {
141. SQLINTEGER    ret;

143. /* 申请环境句柄 */
144. ret = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &h_env);
145. if ((SQL_SUCCESS != ret) && (SQL_SUCCESS_WITH_INFO != ret))
146. {
147. printf("\n begin_unit_test::SQLAllocHandle SQL_HANDLE_ENV failed ! ret = %d", ret);
148. return SQL_ERROR;
149. }

151. /* 进行连接前必须要先设置版本号 */
152. if (SQL_SUCCESS != SQLSetEnvAttr(h_env, SQL_ATTR_ODBC_VERSION, (SQLPOINTER)SQL_OV_ODBC3, 0))
153. {
154. print_error();
155. printf("\n begin_unit_test::SQLSetEnvAttr SQL_ATTR_ODBC_VERSION failed ! ret = %d", ret);
156. SQLFreeHandle(SQL_HANDLE_ENV, h_env);
157. return SQL_ERROR;
158. }

160. /* 申请连接句柄 */
161. ret = SQLAllocHandle(SQL_HANDLE_DBC, h_env, &h_conn);
162. if (SQL_SUCCESS != ret)
163. {
164. print_error();
165. printf("\n begin_unit_test::SQLAllocHandle SQL_HANDLE_DBC failed ! ret = %d", ret);
166. SQLFreeHandle(SQL_HANDLE_ENV, h_env);
167. return SQL_ERROR;
168. }

170. /* 建立连接 */
171. ret = SQLConnect(h_conn, (SQLCHAR*) "gaussdb", SQL_NTS,
172. (SQLCHAR*) NULL, 0, NULL, 0);
173. if (SQL_SUCCESS != ret)
174. {
175. print_error();
176. printf("\n begin_unit_test::SQLConnect  failed ! ret = %d", ret);
177. SQLFreeHandle(SQL_HANDLE_DBC, h_conn);
178. SQLFreeHandle(SQL_HANDLE_ENV, h_env);
179. return SQL_ERROR;
180. }

182. /* 申请语句句柄 */
183. ret = SQLAllocHandle(SQL_HANDLE_STMT, h_conn, &h_stmt);
184. if (SQL_SUCCESS != ret)
185. {
186. print_error();
187. printf("\n begin_unit_test::SQLAllocHandle SQL_HANDLE_STMT failed ! ret = %d", ret);
188. SQLFreeHandle(SQL_HANDLE_DBC, h_conn);
189. SQLFreeHandle(SQL_HANDLE_ENV, h_env);
190. return SQL_ERROR;
191. }

193. return SQL_SUCCESS;
194. }

196. void end_unit_test()
197. {
198. /* 释放语句句柄 */
199. if (NULL != h_stmt)
200. {
201. SQLFreeHandle(SQL_HANDLE_STMT, h_stmt);
202. }

204. /* 释放连接句柄 */
205. if (NULL != h_conn)
206. {
207. SQLDisconnect(h_conn);
208. SQLFreeHandle(SQL_HANDLE_DBC, h_conn);
209. }

211. /* 释放环境句柄 */
212. if (NULL != h_env)
213. {
214. SQLFreeHandle(SQL_HANDLE_ENV, h_env);
215. }

217. return;
218. }

220. int main()
221. {
222. // begin test
223. if (begin_unit_test() != SQL_SUCCESS)
224. {
225. printf("\n begin_test_unit failed.");
226. return SQL_ERROR;
227. }
228. // 句柄配置同前面用例
229. int         i = 0;
230. SQLCHAR*    sql_drop   = "drop table if exists test_bindnumber_001";
231. SQLCHAR*    sql_create = "create table test_bindnumber_001("
232. "f4 number, f5 number(10, 2)"
233. ")";
234. SQLCHAR*    sql_insert = "insert into test_bindnumber_001 values(?, ?)";
235. SQLCHAR*    sql_select = "select * from test_bindnumber_001";
236. SQLLEN      RowCount;
237. SQL_NUMERIC_STRUCT st_number;
238. SQLCHAR     getValue[2][MESSAGE_BUFFER_LEN];

240. /* step 1. 建表 */
241. RETURN_IF_NOT_SUCCESS(execute_cmd(sql_drop));
242. RETURN_IF_NOT_SUCCESS(execute_cmd(sql_create));

244. /* step 2.1 通过SQL_NUMERIC_STRUCT结构绑定参数 */
245. RETURN_IF_NOT_SUCCESS(SQLPrepare(h_stmt, sql_insert, SQL_NTS));

247. //第一行: 1234.5678
248. memset(st_number.val, 0, SQL_MAX_NUMERIC_LEN);
249. st_number.precision = 8;
250. st_number.scale = 4;
251. st_number.sign = 1;
252. st_number.val[0] = 0x4E;
253. st_number.val[1] = 0x61;
254. st_number.val[2] = 0xBC;

256. 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));
257. 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));

259. // 关闭自动提交
260. SQLSetConnectAttr(h_conn, SQL_ATTR_AUTOCOMMIT, (SQLPOINTER)SQL_AUTOCOMMIT_OFF, 0);

262. RETURN_IF_NOT_SUCCESS(commit_exec());
263. RETURN_IF_NOT_SUCCESS(SQLRowCount(h_stmt, &RowCount));
264. RETURN_IF_NOT(1, RowCount);

266. //第二行: 12345678
267. memset(st_number.val, 0, SQL_MAX_NUMERIC_LEN);
268. st_number.precision = 8;
269. st_number.scale = 0;
270. st_number.sign = 1;
271. st_number.val[0] = 0x4E;
272. st_number.val[1] = 0x61;
273. st_number.val[2] = 0xBC;

275. 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));
276. 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));
277. RETURN_IF_NOT_SUCCESS(commit_exec());
278. RETURN_IF_NOT_SUCCESS(SQLRowCount(h_stmt, &RowCount));
279. RETURN_IF_NOT(1, RowCount);

281. //第三行: 12345678
282. memset(st_number.val, 0, SQL_MAX_NUMERIC_LEN);
283. st_number.precision = 0;
284. st_number.scale = 4;
285. st_number.sign = 1;
286. st_number.val[0] = 0x4E;
287. st_number.val[1] = 0x61;
288. st_number.val[2] = 0xBC;

290. 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));
291. 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));
292. RETURN_IF_NOT_SUCCESS(commit_exec());
293. RETURN_IF_NOT_SUCCESS(SQLRowCount(h_stmt, &RowCount));
294. RETURN_IF_NOT(1, RowCount);

297. /* step 2.2 第四行通过SQL_C_CHAR字符串绑定参数 */
298. RETURN_IF_NOT_SUCCESS(SQLPrepare(h_stmt, sql_insert, SQL_NTS));
299. SQLCHAR*    szNumber = "1234.5678";
300. RETURN_IF_NOT_SUCCESS(SQLBindParameter(h_stmt, 1, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_NUMERIC, strlen(szNumber), 0, szNumber, 0, NULL));
301. RETURN_IF_NOT_SUCCESS(SQLBindParameter(h_stmt, 2, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_NUMERIC, strlen(szNumber), 0, szNumber, 0, NULL));
302. RETURN_IF_NOT_SUCCESS(commit_exec());
303. RETURN_IF_NOT_SUCCESS(SQLRowCount(h_stmt, &RowCount));
304. RETURN_IF_NOT(1, RowCount);

306. /* step 2.3 第五行通过SQL_C_FLOAT绑定参数 */
307. RETURN_IF_NOT_SUCCESS(SQLPrepare(h_stmt, sql_insert, SQL_NTS));
308. SQLREAL    fNumber = 1234.5678;
309. RETURN_IF_NOT_SUCCESS(SQLBindParameter(h_stmt, 1, SQL_PARAM_INPUT, SQL_C_FLOAT, SQL_NUMERIC, sizeof(fNumber), 4, &fNumber, 0, NULL));
310. RETURN_IF_NOT_SUCCESS(SQLBindParameter(h_stmt, 2, SQL_PARAM_INPUT, SQL_C_FLOAT, SQL_NUMERIC, sizeof(fNumber), 4, &fNumber, 0, NULL));
311. RETURN_IF_NOT_SUCCESS(commit_exec());
312. RETURN_IF_NOT_SUCCESS(SQLRowCount(h_stmt, &RowCount));
313. RETURN_IF_NOT(1, RowCount);

315. /* step 2.4 第六行通过SQL_C_DOUBLE绑定参数 */
316. RETURN_IF_NOT_SUCCESS(SQLPrepare(h_stmt, sql_insert, SQL_NTS));
317. SQLDOUBLE   dNumber = 1234.5678;
318. RETURN_IF_NOT_SUCCESS(SQLBindParameter(h_stmt, 1, SQL_PARAM_INPUT, SQL_C_DOUBLE, SQL_NUMERIC, sizeof(dNumber), 4, &dNumber, 0, NULL));
319. RETURN_IF_NOT_SUCCESS(SQLBindParameter(h_stmt, 2, SQL_PARAM_INPUT, SQL_C_DOUBLE, SQL_NUMERIC, sizeof(dNumber), 4, &dNumber, 0, NULL));
320. RETURN_IF_NOT_SUCCESS(commit_exec());
321. RETURN_IF_NOT_SUCCESS(SQLRowCount(h_stmt, &RowCount));
322. RETURN_IF_NOT(1, RowCount);

324. SQLBIGINT   bNumber1 = 0xFFFFFFFFFFFFFFFF;
325. SQLBIGINT   bNumber2 = 12345;

327. /* step 2.5 第七行通过SQL_C_SBIGINT绑定参数 */
328. RETURN_IF_NOT_SUCCESS(SQLPrepare(h_stmt, sql_insert, SQL_NTS));
329. RETURN_IF_NOT_SUCCESS(SQLBindParameter(h_stmt, 1, SQL_PARAM_INPUT, SQL_C_SBIGINT, SQL_NUMERIC, sizeof(bNumber1), 4, &bNumber1, 0, NULL));
330. RETURN_IF_NOT_SUCCESS(SQLBindParameter(h_stmt, 2, SQL_PARAM_INPUT, SQL_C_SBIGINT, SQL_NUMERIC, sizeof(bNumber2), 4, &bNumber2, 0, NULL));
331. RETURN_IF_NOT_SUCCESS(commit_exec());
332. RETURN_IF_NOT_SUCCESS(SQLRowCount(h_stmt, &RowCount));
333. RETURN_IF_NOT(1, RowCount);

335. /* step 2.6 第八行通过SQL_C_UBIGINT绑定参数 */
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_UBIGINT, SQL_NUMERIC, sizeof(bNumber1), 4, &bNumber1, 0, NULL));
338. RETURN_IF_NOT_SUCCESS(SQLBindParameter(h_stmt, 2, SQL_PARAM_INPUT, SQL_C_UBIGINT, SQL_NUMERIC, sizeof(bNumber2), 4, &bNumber2, 0, NULL));
339. RETURN_IF_NOT_SUCCESS(commit_exec());
340. RETURN_IF_NOT_SUCCESS(SQLRowCount(h_stmt, &RowCount));
341. RETURN_IF_NOT(1, RowCount);

343. SQLLEN  lNumber1 = 0xFFFFFFFFFFFFFFFF;
344. SQLLEN  lNumber2 = 12345;

346. /* step 2.7 第九行通过SQL_C_LONG绑定参数 */
347. RETURN_IF_NOT_SUCCESS(SQLPrepare(h_stmt, sql_insert, SQL_NTS));
348. RETURN_IF_NOT_SUCCESS(SQLBindParameter(h_stmt, 1, SQL_PARAM_INPUT, SQL_C_LONG, SQL_NUMERIC, sizeof(lNumber1), 0, &lNumber1, 0, NULL));
349. RETURN_IF_NOT_SUCCESS(SQLBindParameter(h_stmt, 2, SQL_PARAM_INPUT, SQL_C_LONG, SQL_NUMERIC, sizeof(lNumber2), 0, &lNumber2, 0, NULL));
350. RETURN_IF_NOT_SUCCESS(commit_exec());
351. RETURN_IF_NOT_SUCCESS(SQLRowCount(h_stmt, &RowCount));
352. RETURN_IF_NOT(1, RowCount);

354. /* step 2.8 第十行通过SQL_C_ULONG绑定参数 */
355. RETURN_IF_NOT_SUCCESS(SQLPrepare(h_stmt, sql_insert, SQL_NTS));
356. RETURN_IF_NOT_SUCCESS(SQLBindParameter(h_stmt, 1, SQL_PARAM_INPUT, SQL_C_ULONG, SQL_NUMERIC, sizeof(lNumber1), 0, &lNumber1, 0, NULL));
357. RETURN_IF_NOT_SUCCESS(SQLBindParameter(h_stmt, 2, SQL_PARAM_INPUT, SQL_C_ULONG, SQL_NUMERIC, sizeof(lNumber2), 0, &lNumber2, 0, NULL));
358. RETURN_IF_NOT_SUCCESS(commit_exec());
359. RETURN_IF_NOT_SUCCESS(SQLRowCount(h_stmt, &RowCount));
360. RETURN_IF_NOT(1, RowCount);

362. SQLSMALLINT sNumber = 0xFFFF;

364. /* step 2.9 第十一行通过SQL_C_SHORT绑定参数 */
365. RETURN_IF_NOT_SUCCESS(SQLPrepare(h_stmt, sql_insert, SQL_NTS));
366. RETURN_IF_NOT_SUCCESS(SQLBindParameter(h_stmt, 1, SQL_PARAM_INPUT, SQL_C_SHORT, SQL_NUMERIC, sizeof(sNumber), 0, &sNumber, 0, NULL));
367. RETURN_IF_NOT_SUCCESS(SQLBindParameter(h_stmt, 2, SQL_PARAM_INPUT, SQL_C_SHORT, SQL_NUMERIC, sizeof(sNumber), 0, &sNumber, 0, NULL));
368. RETURN_IF_NOT_SUCCESS(commit_exec());
369. RETURN_IF_NOT_SUCCESS(SQLRowCount(h_stmt, &RowCount));
370. RETURN_IF_NOT(1, RowCount);

372. /* step 2.10 第十二行通过SQL_C_USHORT绑定参数 */
373. RETURN_IF_NOT_SUCCESS(SQLPrepare(h_stmt, sql_insert, SQL_NTS));
374. RETURN_IF_NOT_SUCCESS(SQLBindParameter(h_stmt, 1, SQL_PARAM_INPUT, SQL_C_USHORT, SQL_NUMERIC, sizeof(sNumber), 0, &sNumber, 0, NULL));
375. RETURN_IF_NOT_SUCCESS(SQLBindParameter(h_stmt, 2, SQL_PARAM_INPUT, SQL_C_USHORT, SQL_NUMERIC, sizeof(sNumber), 0, &sNumber, 0, NULL));
376. RETURN_IF_NOT_SUCCESS(commit_exec());
377. RETURN_IF_NOT_SUCCESS(SQLRowCount(h_stmt, &RowCount));
378. RETURN_IF_NOT(1, RowCount);

380. SQLCHAR cNumber = 0xFF;

382. /* step 2.11 第十三行通过SQL_C_TINYINT绑定参数 */
383. RETURN_IF_NOT_SUCCESS(SQLPrepare(h_stmt, sql_insert, SQL_NTS));
384. RETURN_IF_NOT_SUCCESS(SQLBindParameter(h_stmt, 1, SQL_PARAM_INPUT, SQL_C_TINYINT, SQL_NUMERIC, sizeof(cNumber), 0, &cNumber, 0, NULL));
385. RETURN_IF_NOT_SUCCESS(SQLBindParameter(h_stmt, 2, SQL_PARAM_INPUT, SQL_C_TINYINT, SQL_NUMERIC, sizeof(cNumber), 0, &cNumber, 0, NULL));
386. RETURN_IF_NOT_SUCCESS(commit_exec());
387. RETURN_IF_NOT_SUCCESS(SQLRowCount(h_stmt, &RowCount));
388. RETURN_IF_NOT(1, RowCount);

390. /* step 2.12 第十四行通过SQL_C_UTINYINT绑定参数 */
391. RETURN_IF_NOT_SUCCESS(SQLPrepare(h_stmt, sql_insert, SQL_NTS));
392. RETURN_IF_NOT_SUCCESS(SQLBindParameter(h_stmt, 1, SQL_PARAM_INPUT, SQL_C_UTINYINT, SQL_NUMERIC, sizeof(cNumber), 0, &cNumber, 0, NULL));
393. RETURN_IF_NOT_SUCCESS(SQLBindParameter(h_stmt, 2, SQL_PARAM_INPUT, SQL_C_UTINYINT, SQL_NUMERIC, sizeof(cNumber), 0, &cNumber, 0, NULL));
394. RETURN_IF_NOT_SUCCESS(commit_exec());
395. RETURN_IF_NOT_SUCCESS(SQLRowCount(h_stmt, &RowCount));
396. RETURN_IF_NOT(1, RowCount);

398. /* 用字符串类型统一进行期盼 */
399. SQLCHAR*    expectValue[14][2] = {{"1234.5678",             "1234.57"},
400. {"12345678",              "12345678"},
401. {"0",                     "0"},
402. {"1234.5678",             "1234.57"},
403. {"1234.5677",             "1234.57"},
404. {"1234.5678",             "1234.57"},
405. {"-1",                    "12345"},
406. {"18446744073709551615",  "12345"},
407. {"-1",                    "12345"},
408. {"4294967295",            "12345"},
409. {"-1",                    "-1"},
410. {"65535",                 "65535"},
411. {"-1",                    "-1"},
412. {"255",                   "255"},
413. };

415. RETURN_IF_NOT_SUCCESS(execute_cmd(sql_select));
416. while ( SQL_NO_DATA != SQLFetch(h_stmt))
417. {
418. RETURN_IF_NOT_SUCCESS_I(i, SQLGetData(h_stmt, 1, SQL_C_CHAR, &getValue[0], MESSAGE_BUFFER_LEN, NULL));
419. RETURN_IF_NOT_SUCCESS_I(i, SQLGetData(h_stmt, 2, SQL_C_CHAR, &getValue[1], MESSAGE_BUFFER_LEN, NULL));

421. //RETURN_IF_NOT_STRCMP_I(i, expectValue[i][0], getValue[0]);
422. //RETURN_IF_NOT_STRCMP_I(i, expectValue[i][1], getValue[1]);
423. i++;
424. }

426. RETURN_IF_NOT_SUCCESS(SQLRowCount(h_stmt, &RowCount));
427. RETURN_IF_NOT(i, RowCount);
428. SQLCloseCursor(h_stmt);
429. /* step final. 删除表还原环境 */
430. RETURN_IF_NOT_SUCCESS(execute_cmd(sql_drop));

432. end_unit_test();
433. }

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