unixODBC編程(八)使用滾動游標(biāo)
訪問www.tomcoding.com網(wǎng)站,學(xué)習(xí)Oracle內(nèi)部數(shù)據(jù)結(jié)構(gòu),詳細(xì)文檔說明,下載Oracle的exp/imp,DUL,logminer,ASM工具的源代碼,學(xué)習(xí)高技術(shù)含量的內(nèi)容。
Cursor是光標(biāo)的意思,指的是在計算機屏幕上閃爍的一個亮塊或一條豎線,如果在一個文字編輯的屏幕上就更好理解了,光標(biāo)會隨著鍵盤的上下左右鍵相應(yīng)的移動。這個詞在數(shù)據(jù)庫查詢的結(jié)果集中使用時就翻譯成了游標(biāo),與光標(biāo)的區(qū)別是它只能上下移動,代表在不同的數(shù)據(jù)行間選擇。
在一條查詢語句被執(zhí)行后,就生成了一個結(jié)果集,這時游標(biāo)處在第一行數(shù)據(jù)之前,所以取回(fetch)下一條數(shù)據(jù)(SQL_FETCH_NEXT)就是取回第一條數(shù)據(jù)。調(diào)用一次fetch函數(shù),游標(biāo)就停在fetch回的最后一條數(shù)據(jù)上,如果只取回一條,那么游標(biāo)就在這條數(shù)據(jù)上,如果取回多條(使用數(shù)組取回),那么游標(biāo)就停在最后一條數(shù)據(jù)上。
前面我們用到的SQLFetch()函數(shù)只能取回下一條數(shù)據(jù),使用的是一種只能向前滾動的游標(biāo),如果要取回當(dāng)前數(shù)據(jù)之前的某條數(shù)據(jù)就會比較麻煩,只能重新執(zhí)行查詢語句,然后再fetch到想要的那條數(shù)據(jù),即浪費時間,有操作復(fù)雜。為解決這樣的問題,ODBC提供了滾動游標(biāo)(scrollable cursor),這種游標(biāo)可以從任意位置取回結(jié)果集中的數(shù)據(jù)行。要使用滾動游標(biāo),需要設(shè)置語句屬性SQL_ATTR_CURSOR_SCROLLABLE,屬性值為SQL_SCROLLABLE,設(shè)置這個屬性的位置有些特別,要在分配語句句柄后設(shè)置,在SQLPrepare()或SQLExecDirect()函數(shù)調(diào)用之前,否則會出錯。
在執(zhí)行語句后生成了結(jié)果集,這時就可以使用滾動游標(biāo)了,取回數(shù)據(jù)的函數(shù)要使用SQLFetchScroll(),而不是SQLFetch()。我們看一下SQLFetchScroll()的函數(shù)原型和參數(shù)。
SQLRETURN SQLFetchScroll(
SQLHSTMT StatementHandle,
SQLSMALLINT FetchOrientation,
SQLLEN FetchOffset);
StatementHandle是一個輸入?yún)?shù),查詢語句的句柄。
FetchOrientation是一個輸入?yún)?shù),取回數(shù)據(jù)的方向值。取值如下:
SQL_FETCH_NEXT(取下一條)
SQL_FETCH_PRIOR(取當(dāng)前行的前一條)
SQL_FETCH_FIRST(取第一行)
SQL_FETCH_LAST(取最后一行)
SQL_FETCH_ABSOLUTE(按絕對行號取數(shù)據(jù))
SQL_FETCH_RELATIVE(按相對行號取數(shù)據(jù))
SQL_FETCH_BOOKMARK(按書簽取數(shù)據(jù))
FetchOffset是一個輸入?yún)?shù),取數(shù)據(jù)的行號偏移量。對于絕對行號取數(shù)據(jù),偏移量就是某個行號,表示取結(jié)果集中的第幾行。對于相對行號取數(shù)據(jù),偏移量就是相對于當(dāng)前行偏移幾行,如果是正數(shù),就是當(dāng)前行加偏移行的行號,如果是負(fù)數(shù),就是當(dāng)前行減去偏移行的行號。
我們看一個實際的例子,怎樣設(shè)置滾動游標(biāo)屬性,怎樣使用SQLFetchScroll()函數(shù)。
#include "stdio.h" #include "stdlib.h" #include "string.h" #include "sql.h" #include "sqlext.h" #include "sqltypes.h" SQLHANDLE envh; /* env handle */ SQLHANDLE dbch; /* connect handle */ SQLHANDLE stmth; /* statement handle */ int main(int argc, char *argv[]){ int i; int conn = 0; SQLRETURN rc; SQLLEN len_ind1; SQLLEN len_ind2; SQLLEN len_ind3; SQLLEN len_ind4; SQLLEN len_ind5; SQLINTEGER id; char dsn_str[32]; char usrname[32]; char passwd[32]; char sqltxt[128]; char f1[32]; char f2[32]; char f3[32]; char f4[32]; if (argc < 3) { fprintf(stderr, "usage: %s dsn username password\n", argv[0]); return (-1); } strncpy(dsn_str, argv[1], 32); dsn_str[31] = '\0'; strncpy(usrname, argv[2], 32); usrname[31] = '\0'; strncpy(passwd, argv[3], 32); passwd[31] = '\0'; rc = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &envh); if (rc != SQL_SUCCESS) { fprintf(stderr, "Allocate environment handle error.\n"); return (-1); } rc = SQLSetEnvAttr(envh, SQL_ATTR_ODBC_VERSION, (void *)SQL_OV_ODBC3, 0); if (rc != SQL_SUCCESS) { fprintf(stderr, "Set ODBC version error.\n"); goto free_exit; } rc = SQLAllocHandle(SQL_HANDLE_DBC, envh, &dbch); if (rc != SQL_SUCCESS) { fprintf(stderr, "Allocate DB connection handle error.\n"); goto free_exit; } rc = SQLSetConnectAttr(dbch, SQL_ATTR_LOGIN_TIMEOUT, (SQLPOINTER)10, 0); if (rc != SQL_SUCCESS) { fprintf(stderr, "Set connection timeout value error.\n"); goto free_exit; } rc = SQLConnect(dbch, (SQLCHAR *)dsn_str, SQL_NTS, (SQLCHAR *)usrname, SQL_NTS, (SQLCHAR *)passwd, SQL_NTS); if (rc != SQL_SUCCESS) { fprintf(stderr, "Connect to DB error.\n"); goto free_exit; } conn = 1; fprintf(stdout, "connect DB ok ......\n"); rc = SQLAllocHandle(SQL_HANDLE_STMT, dbch, &stmth); if (rc != SQL_SUCCESS) { fprintf(stderr, "Allocate statment handle error.\n"); goto free_exit; } /* 設(shè)置結(jié)果集使用滾動游標(biāo) */ rc = SQLSetStmtAttr(stmth, SQL_ATTR_CURSOR_SCROLLABLE, (SQLPOINTER)SQL_SCROLLABLE, 0); if (rc != SQL_SUCCESS) { fprintf(stderr, "Set statment attribute error.\n"); goto free_exit; } /* 準(zhǔn)備語句 */ sprintf(sqltxt, "select id, f1, f2, f3, f4 from my_tredo1"); rc = SQLPrepare(stmth, (SQLCHAR *)sqltxt, SQL_NTS); if (rc != SQL_SUCCESS) { fprintf(stderr, "Prepare statment error.\n"); goto free_exit; } rc = SQLBindCol(stmth, 1, SQL_C_ULONG, (SQLPOINTER)&id, 0, &len_ind1); if (rc != SQL_SUCCESS) { fprintf(stderr, "Bind column 1 error.\n"); goto free_exit; } rc = SQLBindCol(stmth, 2, SQL_C_CHAR, (SQLPOINTER)f1, 32, &len_ind2); if (rc != SQL_SUCCESS) { fprintf(stderr, "Bind column 2 error.\n"); goto free_exit; } rc = SQLBindCol(stmth, 3, SQL_C_CHAR, (SQLPOINTER)f2, 32, &len_ind3); if (rc != SQL_SUCCESS) { fprintf(stderr, "Bind column 3 error.\n"); goto free_exit; } rc = SQLBindCol(stmth, 4, SQL_C_CHAR, (SQLPOINTER)f3, 32, &len_ind4); if (rc != SQL_SUCCESS) { fprintf(stderr, "Bind column 4 error.\n"); goto free_exit; } rc = SQLBindCol(stmth, 5, SQL_C_CHAR, (SQLPOINTER)f4, 32, &len_ind5); if (rc != SQL_SUCCESS) { fprintf(stderr, "Bind column 4 error.\n"); goto free_exit; } rc = SQLExecute(stmth); if (rc != SQL_SUCCESS) { fprintf(stderr, "Execute statment error.\n"); goto free_exit; } /* 先使用SQL_FETCH_NEXT參數(shù),把結(jié)果集中的數(shù)據(jù)行都打印出來 */ for (i=1; ;i++) { rc = SQLFetchScroll(stmth, SQL_FETCH_NEXT, 0); if (rc == SQL_NO_DATA) { fprintf(stderr, "no data in result set, break.\n"); break; } else if (rc == SQL_ERROR) { fprintf(stderr, "Fetch data error.\n"); goto free_exit; } fprintf(stdout, "row[%02d] id=%d, f1=%s, f2=%s, f3=%s, f4=%s\n", i, id, f1, f2, f3, f4); } /* 取回第一條數(shù)據(jù),打印顯示 */ rc = SQLFetchScroll(stmth, SQL_FETCH_FIRST, 0); if (rc != SQL_SUCCESS) { fprintf(stderr, "Fetch the first row error.\n"); goto free_exit; } fprintf(stderr, "The first row:\nid=%d, f1=%s, f2=%s, f3=%s, f4=%s\n", id, f1, f2, f3, f4); /* 取回最后一條數(shù)據(jù),打印顯示 */ rc = SQLFetchScroll(stmth, SQL_FETCH_LAST, 0); if (rc != SQL_SUCCESS) { fprintf(stderr, "Fetch the last row error.\n"); goto free_exit; } fprintf(stderr, "The last row:\nid=%d, f1=%s, f2=%s, f3=%s, f4=%s\n", id, f1, f2, f3, f4); /* 取回倒數(shù)第二行數(shù)據(jù),打印顯示 */ rc = SQLFetchScroll(stmth, SQL_FETCH_PRIOR, 0); if (rc != SQL_SUCCESS) { fprintf(stderr, "Fetch the second to last row error.\n"); goto free_exit; } fprintf(stderr, "The second to last row:\nid=%d, f1=%s, f2=%s, f3=%s, f4=%s\n", id, f1, f2, f3, f4); /* 使用相對行號,取回倒數(shù)第二條的前一條,就是倒數(shù)第三行的數(shù)據(jù) */ rc = SQLFetchScroll(stmth, SQL_FETCH_RELATIVE, -1); if (rc != SQL_SUCCESS) { fprintf(stderr, "Fetch the third to last row error.\n"); goto free_exit; } fprintf(stderr, "The third to last row:\nid=%d, f1=%s, f2=%s, f3=%s, f4=%s\n", id, f1, f2, f3, f4); /* 使用絕對行號,取回第五行的數(shù)據(jù) */ rc = SQLFetchScroll(stmth, SQL_FETCH_ABSOLUTE, 5); if (rc != SQL_SUCCESS) { fprintf(stderr, "Fetch the fifth row error.\n"); goto free_exit; } fprintf(stderr, "The fifth row:\nid=%d, f1=%s, f2=%s, f3=%s, f4=%s\n", id, f1, f2, f3, f4); /* 關(guān)閉游標(biāo) */ SQLCloseCursor(stmth); SQLFreeHandle(SQL_HANDLE_STMT, stmth); SQLDisconnect(dbch); SQLFreeHandle(SQL_HANDLE_DBC, dbch); SQLFreeHandle(SQL_HANDLE_ENV, envh); return (0); free_exit: if (stmth != NULL) { SQLFreeHandle(SQL_HANDLE_STMT, stmth); } if (conn) { SQLDisconnect(dbch); } if (dbch != NULL) { SQLFreeHandle(SQL_HANDLE_DBC, dbch); } if (envh != NULL) { SQLFreeHandle(SQL_HANDLE_ENV, envh); } return (-1); }
訪問www.tomcoding.com網(wǎng)站,學(xué)習(xí)Oracle內(nèi)部數(shù)據(jù)結(jié)構(gòu),詳細(xì)文檔說明,下載Oracle的exp/imp,DUL,logminer,ASM工具的源代碼,學(xué)習(xí)高技術(shù)含量的內(nèi)容。

浙公網(wǎng)安備 33010602011771號