使用游标获取结果
默认情况下,驱动程序将一次性获取查询的所有结果,当某个查询的结果集很庞大时,一次获取所有结果很不合理,因此ODBC驱动程序提供了一种基于数据库游标的结果集处理方法,只获取少量的行缓存在客户端。通过重新定位游标来获取下一批数据。
游标不能在所有情况下使用。有许多限制会使驱动程序一次性获取整个结果集:
连接不能使用自动提交模式 ,因为后端会在事务结束时关闭游标,因此在自动提交模式下,事务结束后,在从游标获取数据之前,游标已经被关闭。
UseDeclareFetch参数设置为true,默认缓存 100行数据,为false时将不会使用游标,直接获取整个结果集。
给定的查询语句必须是单条语句,不能是用分号连接在一起的多个语句。
设置fetch size,且fetch size不能为0.
示例:
int rc;
int i;
/*关闭自动提交*/
rc = SQLSetConnectAttr(V_OD_hdbc, SQL_AUTOCOMMIT, (SQLPOINTER) SQL_AUTOCOMMIT_OFF, 0);
CHECK_CONN_RESULT(rc, "SQL_AUTOCOMMIT off failed", V_OD_hdbc);
/*执行SQL*/
rc = SQLExecDirect(V_OD_hstmt, (SQLCHAR *) "SELECT 'foo' || g FROM generate_series(1, 3210) g", SQL_NTS);
CHECK_STMT_RESULT(rc, "SQLExecDirect failed", V_OD_hstmt);
/*获取结果*/
for (;; i++)
{
char buf[40];
SQLLEN ind;
rc = SQLFetch(V_OD_hstmt);
if (rc == SQL_NO_DATA)
break;
if (rc != SQL_SUCCESS)
{
char sqlstate[32] = "";
SQLINTEGER nativeerror;
SQLSMALLINT textlen;
SQLGetDiagRec(SQL_HANDLE_STMT, V_OD_hstmt, 1, sqlstate, &nativeerror, NULL, 0, &textlen);
/*在读取游标的过程中,如果调用用SQLEndTran提交或回滚了事务,游标将被关闭*/
if (strcmp(sqlstate, "HY010") == 0)
{
printf("SQLFetch failed with HY010 (which probably means that the cursor was closed at commit/rollback)");
break;
}
else
CHECK_STMT_RESULT(rc, "SQLGetDiagRec failed", V_OD_hstmt);
}
rc = SQLGetData(V_OD_hstmt, 1, SQL_C_CHAR, buf, sizeof(buf), &ind);
CHECK_STMT_RESULT(rc, "SQLGetData failed", V_OD_hstmt);
}