示例3:使用书签

使用书签的行集提取

此示例显示使用SQLFetchSroll并设置 FetchOrientation为SQL_FETCH_BOOKMARK的行集提取操作。

#include <string.h>
#include <sql.h>
#include <sqlext.h>
#include <sqltypes.h>
#include <odbcss.h>
#include <stdio.h>
#define ROW_ARRAY_SIZE 10
SQLUINTEGER NumRowsFetched;
SQLUSMALLINT RowStatusArray[ROW_ARRAY_SIZE];
SQLCHAR BookMark[10];
RETCODE retcode;
SQLHENV henv = SQL_NULL_HENV;
SQLHDBC hdbc1 = SQL_NULL_HDBC;
SQLHSTMT hstmt1 = SQL_NULL_HSTMT;
int main()
{
// 分配ODBC环境句柄
    retcode = SQLAllocHandle (SQL_HANDLE_ENV, NULL, &henv);
// 指定应用程序ODBC版本
    retcode = SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION,(SQLPOINTER)
                            SQL_OV_ODBC3, SQL_IS_INTEGER);
// 分配ODBC连接句柄并连接
    retcode = SQLAllocHandle(SQL_HANDLE_DBC, henv, &hdbc1);
    retcode = SQLConnect(hdbc1,(SQLCHAR*)"OSRDBSource",
                         SQL_NTS,(SQLCHAR*)"sysdba", SQL_NTS,
                         (SQLCHAR*)"szoscar55",SQL_NTS);
// 分配语句句柄
    retcode = SQLAllocHandle(SQL_HANDLE_STMT, hdbc1, &hstmt1);
// 设置游标类型
// 设置游标行集的大小
// 设置存放行集实际获取的行数的程序变量
// 设置存放行集每一行数据读取情况的状态矩阵
// 设置使用变长书签
// 设置存放书签的程序变量
    SQLSetStmtAttr(hstmt1, SQL_ATTR_CURSOR_TYPE,
                   (SQLPOINTER)SQL_CURSOR_KEYSET_DRIVEN, 0);
    SQLSetStmtAttr(hstmt1, SQL_ATTR_ROW_ARRAY_SIZE,
                   (SQLPOINTER)ROW_ARRAY_SIZE, 0);
    SQLSetStmtAttr(hstmt1, SQL_ATTR_ROWS_FETCHED_PTR, &NumRowsFetched,
                   0);
    SQLSetStmtAttr(hstmt1, SQL_ATTR_ROW_STATUS_PTR, RowStatusArray, 0);
    SQLSetStmtAttr(hstmt1, SQL_ATTR_USE_BOOKMARKS,
                   (SQLPOINTER)SQL_UB_VARIABLE, 0);
    SQLSetStmtAttr(hstmt1, SQL_ATTR_FETCH_BOOKMARK_PTR,
                   (SQLPOINTER)BookMark, 0);
// 执行SQL语句
    SQLExecDirect(hstmt1, (SQLCHAR*)"SELECT ID, USER_NAME FROM USERS",
                  SQL_NTS);
// 获取任意行的书签,此处实际获取的是结果集第6行的书签
    SQLFetchScroll(hstmt1, SQL_FETCH_NEXT, 0);
    SQLSetPos(hstmt1, 6, SQL_POSITION, SQL_LOCK_NO_CHANGE);
    SQLGetData(hstmt1, 0, SQL_C_CHAR, (SQLPOINTER)BookMark, 10, NULL);
// 使用SQL_FETCH_BOOKMARK,获取从书签指定的行开始的行集
    SQLFetchScroll(hstmt1, SQL_FETCH_BOOKMARK, 0);
// Close the cursor.
    SQLCloseCursor(hstmt1);
// 释放语句句柄
// 断开连接
// 释放连接句柄和环境句柄
    SQLFreeHandle(SQL_HANDLE_STMT, hstmt1);
    SQLDisconnect(hdbc1);
    SQLFreeHandle(SQL_HANDLE_DBC, hdbc1);
    SQLFreeHandle(SQL_HANDLE_ENV, henv);
    return 0;
}

使用书签的批量操作

此示例显示使用SQLBulkOperation并借助书签的批量操作。示例先获取一个大小为10的行集的游标,之后对行集中的偶数行进行FETCH/UPDATE/DELETE操作。

#include <string.h>
            #include <sql.h>
            #include <sqlext.h>
            #include <sqltypes.h>
            #include <odbcss.h>
            #include <stdio.h>
            #define MAX_STR_LEN 65
            #define ROW_ARRAY_SIZE 10
            typedef struct tagBookmarkStruct {
                SQLCHAR Bookmark[10];
                SQLINTEGER BookmarkLen;
            }BookmarkStruct;
            typedef struct tagUserStruct {
                SQLCHAR Bookmark[10];
                SQLINTEGER BookmarkLen;
                SQLINTEGER UserID;
                SQLINTEGER UserIDInd;
                SQLCHAR UserName[MAX_STR_LEN];
                SQLINTEGER UserNameInd;
            } UserStruct;
            SQLUINTEGER NumRowsFetched;
            BookmarkStruct BookmarkArray[ROW_ARRAY_SIZE];
            UserStruct UserArray[ROW_ARRAY_SIZE/2];
            SQLUSMALLINT RowStatusArray[10], Action, RowNum,i;
            RETCODE retcode;
            SQLHENV henv = SQL_NULL_HENV;
            SQLHDBC hdbc1 = SQL_NULL_HDBC;
            SQLHSTMT hstmt1 = SQL_NULL_HSTMT;
            int GetAction(SQLUSMALLINT *a,SQLUSMALLINT *b)
            {
                *a = 4;
                *b = 1;
                return 1;
            }
            int GetNewData(SQLINTEGER *a,SQLINTEGER *b,SQLCHAR *c,SQLINTEGER *d)
            {
                *a = 11;
                *b = 0;
                *d = -3;
                strcpy((char*)c ,"fsggfs");
                return 1;
            }
            int main()
            {
            // 分配ODBC环境句柄
                retcode = SQLAllocHandle (SQL_HANDLE_ENV, NULL, &henv);
            // 指定应用程序ODBC版本
                retcode = SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION,(SQLPOINTER)
                                        SQL_OV_ODBC3, SQL_IS_INTEGER);
            // 分配ODBC连接句柄并连接
                retcode = SQLAllocHandle(SQL_HANDLE_DBC, henv, &hdbc1);
                retcode = SQLConnect(hdbc1,(SQLCHAR*)"OSRDBSource",
                                     SQL_NTS,(SQLCHAR*)"sysdba", SQL_NTS,
                                     (SQLCHAR*)"szoscar55",SQL_NTS);
            // 分配语句句柄
                retcode = SQLAllocHandle(SQL_HANDLE_STMT, hdbc1, &hstmt1);
            // 设置游标类型
            // 设置绑定模式为row-wise
            // 设置游标行集的大小
            // 设置存放行集实际获取的行数的程序变量
            // 设置存放行集每一行数据读取情况的状态矩阵
            // 设置使用变长书签
                retcode = SQLSetStmtAttr(hstmt1, SQL_ATTR_CURSOR_TYPE,
                                         (SQLPOINTER)SQL_CURSOR_KEYSET_DRIVEN, 0);
                retcode = SQLSetStmtAttr(hstmt1, SQL_ATTR_ROW_BIND_TYPE,
                                         (SQLPOINTER)SQL_BIND_TYPE_DEFAULT, 0);
                retcode = SQLSetStmtAttr(hstmt1, SQL_ATTR_ROW_ARRAY_SIZE,
                                         (SQLPOINTER)ROW_ARRAY_SIZE, 0);
                retcode = SQLSetStmtAttr(hstmt1, SQL_ATTR_ROWS_FETCHED_PTR,
                                         &NumRowsFetched, 0);
                retcode = SQLSetStmtAttr(hstmt1, SQL_ATTR_ROW_STATUS_PTR,
                                         RowStatusArray, 0);
                retcode = SQLSetStmtAttr(hstmt1, SQL_ATTR_USE_BOOKMARKS,
                                         (SQLPOINTER)SQL_UB_VARIABLE, 0);
            // 执行SQL语句
                retcode = SQLExecDirect(hstmt1, (SQLCHAR*)"SELECT ID, USER_NAME FROM
                                        USERS", SQL_NTS);
                /****** 获取批量操作使用的书签******/
                retcode = SQLBindCol(hstmt1, 0, SQL_C_VARBOOKMARK,
                                     BookmarkArray[0].Bookmark,
                                     sizeof(BookmarkArray[0].Bookmark), &BookmarkArray[0].BookmarkLen);
                retcode = SQLFetchScroll(hstmt1, SQL_FETCH_NEXT, 0);
                /****** 执行批量操作******/
            // 设置批量操作的行数
                retcode = SQLSetStmtAttr(hstmt1, SQL_ATTR_ROW_ARRAY_SIZE,
                                         (SQLPOINTER)(ROW_ARRAY_SIZE/2), 0);
            // 重新绑定结果集缓存
                retcode = SQLBindCol(hstmt1, 0, SQL_C_VARBOOKMARK,
                                     UserArray[0].Bookmark,sizeof(UserArray[0].Bookmark),
                                     &UserArray[0].BookmarkLen);
                retcode = SQLBindCol(hstmt1, 1, SQL_C_ULONG, &UserArray[0].UserID, 0,
                                     &UserArray[0].UserIDInd);
                retcode = SQLBindCol(hstmt1, 2, SQL_C_CHAR, UserArray[0].UserName,
                                     sizeof(UserArray[0].UserName),&UserArray[0].UserNameInd);
            // 应用程序获取用户需要的SQLBulkOperation操作类型
                if (GetAction(&Action, &RowNum))
                {
                    switch (Action) {
                    case SQL_ADD:
                        for ( i = 0; i < ROW_ARRAY_SIZE/2; i ++)
                        {
            // 重新填充行集中指定行的绑定缓冲区
                            GetNewData(&UserArray[i].UserID, &UserArray[i].UserIDInd ,
                                       UserArray[i].UserName, &UserArray[i].UserNameInd);
            // SQL_ADD操作不需要使用书签
                        }
                        retcode = SQLBulkOperations(hstmt1, SQL_ADD);
                        break;
                    case SQL_FETCH_BY_BOOKMARK:
                        for (i = 0; i < ROW_ARRAY_SIZE/2; i ++)
                        {
            // 获取该行对应的书签
                            memcpy(UserArray[i].Bookmark, BookmarkArray[2*i].Bookmark,
                                   BookmarkArray[2*i].BookmarkLen);
                        }
                        SQLBulkOperations(hstmt1, SQL_FETCH_BY_BOOKMARK);
                        break;
                    case SQL_DELETE_BY_BOOKMARK:
                        for (i = 0; i < ROW_ARRAY_SIZE/2; i ++)
                        {
            // 获取该行对应的书签
                            memcpy(UserArray[i].Bookmark, BookmarkArray[2*i].Bookmark,
                                   BookmarkArray[2*i].BookmarkLen);
                        }
                        SQLBulkOperations(hstmt1, SQL_DELETE_BY_BOOKMARK);
                    case SQL_UPDATE_BY_BOOKMARK:
                        for (i = 0; i < ROW_ARRAY_SIZE/2; i ++)
                        {
            // 重新填充行集中指定行的绑定缓冲区
                            GetNewData(&UserArray[i].UserID, &UserArray[i].UserIDInd ,
                                       UserArray[i].UserName, &UserArray[i].UserNameInd);
            // 获取该行对应的书签
                            memcpy(UserArray[i].Bookmark, BookmarkArray[2*i].Bookmark,
                                   BookmarkArray[2*i].BookmarkLen);
                        }
                        SQLBulkOperations(hstmt1, SQL_UPDATE_BY_BOOKMARK);
                        break;
                    }
                }
            // 关闭游标
                SQLFreeStmt(hstmt1, SQL_CLOSE);
            // 释放语句句柄
            // 断开连接
            // 释放连接句柄和环境句柄
                SQLFreeHandle(SQL_HANDLE_STMT, hstmt1);
                SQLDisconnect(hdbc1);
                SQLFreeHandle(SQL_HANDLE_DBC, hdbc1);
                SQLFreeHandle(SQL_HANDLE_ENV, henv);
                return 0;
            }