示例2:行集的定位与操作

此示例显示了使用SQLSetPos对行集中指定行进行定位更新删除插入操作。示例使用的行集大小为10,存放数据的数组大小为11,其中前10行用于放置获取的行集数据,第11行用于放置插入操作使用的新数据。

#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
SQLINTEGER UserIDArray[ROW_ARRAY_SIZE + 1];
SQLCHAR UserNameArray[ROW_ARRAY_SIZE + 1] [MAX_STR_LEN];
SQLINTEGER UserIDIndArray[ROW_ARRAY_SIZE + 1],
UserNameIndArray[ROW_ARRAY_SIZE + 1];
SQLUSMALLINT RowStatusArray[10], RowNum, Action;
RETCODE retcode;
SQLHENV henv = SQL_NULL_HENV;
SQLHDBC hdbc1 = SQL_NULL_HDBC;
SQLHSTMT hstmt1 = SQL_NULL_HSTMT;
SQLCHAR errmsg[10];
SQLINTEGER errint;
SQLSMALLINT errind;
SQLCHAR errdesc[512];
int errLineNum = 0 ;
int GetAction(SQLUSMALLINT *a,SQLUSMALLINT *b)
{
    *a = 0;
    *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);
// 设置游标类型
// 设置结果集绑定方式
// 设置游标行集的大小
// 设置存放行集每一行数据读取情况的状态矩阵
    SQLSetStmtAttr(hstmt1, SQL_ATTR_CURSOR_TYPE,
                   (SQLPOINTER)SQL_CURSOR_KEYSET_DRIVEN, 0);
    SQLSetStmtAttr(hstmt1, SQL_ATTR_ROW_BIND_TYPE,
                   SQL_BIND_BY_COLUMN, 0);
    SQLSetStmtAttr(hstmt1, SQL_ATTR_ROW_ARRAY_SIZE,
                   (SQLPOINTER)ROW_ARRAY_SIZE, 0);
    SQLSetStmtAttr(hstmt1, SQL_ATTR_ROW_STATUS_PTR, RowStatusArray, 0);
// 绑定结果集
    SQLBindCol(hstmt1, 1, SQL_C_SLONG, UserIDArray, 0, UserIDIndArray);
    SQLBindCol(hstmt1, 2, SQL_C_CHAR, UserNameArray,
               sizeof(UserNameArray[0]),UserNameIndArray);
// 执行SQL语句
    SQLExecDirect(hstmt1, (SQLCHAR*)"SELECT ID, USER_NAME FROM Users",
                  SQL_NTS);
// 移动游标获取一个行集
    retcode = SQLFetchScroll(hstmt1, SQL_FETCH_NEXT, 0);
// 应用程序获取用户需要的SQLSetPos操作类型和要操作的行的编号
    if (GetAction(&Action, &RowNum))
    {
        switch (Action) {
        case SQL_POSITION:
            retcode = SQLSetPos(hstmt1, RowNum, SQL_POSITION,
                                SQL_LOCK_NO_CHANGE);
            break;
        case SQL_UPDATE:
// 重新填充行集中指定行的绑定缓冲区并执行UPDATE
            GetNewData(&UserIDArray[RowNum - 1], &UserIDIndArray[RowNum - 1],
                       UserNameArray[RowNum - 1], &UserNameIndArray[RowNum - 1]);
            SQLSetPos(hstmt1, RowNum, SQL_UPDATE, SQL_LOCK_NO_CHANGE);
            break;
        case SQL_DELETE:
// 删除指定行
            SQLSetPos(hstmt1, RowNum, SQL_DELETE, SQL_LOCK_NO_CHANGE);
            break;
        case SQL_ADD:
// 使用绑定数组的额外元素执行插入操作
            GetNewData(&UserIDArray[10], &UserIDIndArray[10],UserNameArray[10],
                       &UserNameIndArray[10]);
            retcode = SQLSetPos(hstmt1, 11, SQL_ADD, SQL_LOCK_NO_CHANGE);
            break;
        }
        if (SQL_NO_DATA!=SQLGetDiagRec(SQL_HANDLE_STMT, hstmt1, ++errLineNum,
                                       errmsg, &errint, (SQLCHAR *)errdesc, (SQLSMALLINT)500, &errind))
        {
            printf("%s: %sn", errmsg, errdesc);
            printf("n");
            char c =getchar();
        }
    }
// Close the cursor.
    SQLCloseCursor(hstmt1);
// 释放语句句柄
// 断开连接
// 释放连接句柄和环境句柄
    SQLFreeHandle(SQL_HANDLE_STMT, hstmt1);
    SQLDisconnect(hdbc1);
    SQLFreeHandle(SQL_HANDLE_DBC, hdbc1);
    SQLFreeHandle(SQL_HANDLE_ENV, henv);
    return 0;
}