示例1:移动和提取行集¶
游标的一般移动¶
此示例显示使用键集游标并调用SQLFetchScroll在结果集进行移动。
简单起见,该示例没有通过SQLBindCol或SQLGetData提取结果集的数据,并省略了错误处理的代码。
#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];
SQLINTEGER RowNum, i;
SQLHENV henv = SQL_NULL_HENV;
SQLHDBC hdbc1 = SQL_NULL_HDBC;
SQLHSTMT hstmt1 = SQL_NULL_HSTMT;
int main()
{
RETCODE retcode;
// 分配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);
// 执行SQL语句
SQLExecDirect(hstmt1, (SQLCHAR*)"SELECT ID, USER_NAME FROM USERS",
SQL_NTS);
// 使用SQL_FETCH_NEXT,获取下一行集
SQLFetchScroll(hstmt1, SQL_FETCH_NEXT, 0);
// 或使用SQL_FETCH_PRIOR,获取前一行集
//SQLFetchScroll(hstmt1, SQL_FETCH_PRIOR, 0);
// 或使用SQL_FETCH_FIRST,获取从结果集第行开始的行集
//SQLFetchScroll(hstmt1, SQL_FETCH_FIRST,0);
// 或使用SQL_FETCH_LAST,获取以结果集倒数第行结束的行集
//SQLFetchScroll(hstmt1, SQL_FETCH_LAST, 0);
// 或使用SQL_FETCH_ABSOLUTE,获取从结果集第RowNum行开始的行集
//SQLFetchScroll(hstmt1, SQL_FETCH_ABSOLUTE, RowNum);
// 或使用SQL_FETCH_RELATIVE,获取当前行偏移RowNum行开始的行集
//SQLFetchScroll(hstmt1, SQL_FETCH_RELATEIVE, RowNum);
// 根据行集状态矩阵,获取对应行的状态
for (i = 0; i < NumRowsFetched; i++)
{
printf("Row Set Statusn");
printf("------------- -------------n");
switch (RowStatusArray[i])
{
case SQL_ROW_SUCCESS:
case SQL_ROW_SUCCESS_WITH_INFO:
printf("%13d Successn", i);
break;
case SQL_ROW_ERROR:
printf("%13d Errorn", i);
break;
case SQL_ROW_UPDATED:
printf("%13d Updatedn", i);
break;
case SQL_ROW_DELETED:
printf("%13d Deletedn", i);
break;
case SQL_ROW_ADDED:
printf("%13d Addedn", i);
break;
case SQL_ROW_NOROW:
printf("%13d No row is found!n", i);
break;
}
}
// 释放语句句柄
// 断开连接
// 释放连接句柄和环境句柄
SQLFreeHandle(SQL_HANDLE_STMT, hstmt1);
SQLDisconnect(hdbc1);
SQLFreeHandle(SQL_HANDLE_DBC, hdbc1);
SQLFreeHandle(SQL_HANDLE_ENV, henv);
return 0;
}
列宽绑定(数组绑定)¶
此示例显示在使用行集大小为10的块游标时,使用列宽集绑定方式(column-wise)提取行集的数据。
#include <string.h>
#include <sql.h>
#include <sqlext.h>
#include <sqltypes.h>
#include <odbcss.h>
#include <stdio.h>
#define MAXBUFLEN 255
#define ROW_ARRAY_SIZE 10
SQLUINTEGER NumRowFetched;
SQLUSMALLINT RowStatusArray[ROW_ARRAY_SIZE];
SQLCHAR UserNameArray[ROW_ARRAY_SIZE][MAXBUFLEN];
SQLINTEGER UserIDArray[ROW_ARRAY_SIZE],
UserIDIndArray[ROW_ARRAY_SIZE],
UserNameIndArray[ROW_ARRAY_SIZE];
SQLCHAR szName[MAXNAME+1];
SQLINTEGER szID;
SQLINTEGER cbName;
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, &NumRowFetched,
0);
SQLSetStmtAttr(hstmt1, SQL_ATTR_ROW_STATUS_PTR, RowStatusArray, 0);
// 设置结果集绑定方式
SQLSetStmtAttr(hstmt1, SQL_ATTR_ROW_BIND_TYPE,
SQL_BIND_BY_COLUMN, 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);
// 调用一次SQLFetchScroll就可以获取行集的所有行
while ((retcode = SQLFetchScroll(hstmt1,SQL_FETCH_NEXT,0))
!=SQL_NO_DATA)
{
for (int i = 0; i < NumRowFetched; i ++)
{
// 根据行的状态决定获取的数据是否有效
if (RowStatusArray[i] != SQL_ROW_ERROR && RowStatusArray[i] !=
SQL_ROW_DELETED &&RowStatusArray[i] != SQL_ROW_NOROW)
{
printf("User ID : %d, User Name : %sn", UserIDArray[i],
UserNameArray[i]);
}
}
}
// Close the cursor.
SQLCloseCursor(hstmt1);
// 释放语句句柄
// 断开连接
// 释放连接句柄和环境句柄
SQLFreeHandle(SQL_HANDLE_STMT, hstmt1);
SQLDisconnect(hdbc1);
SQLFreeHandle(SQL_HANDLE_DBC, hdbc1);
SQLFreeHandle(SQL_HANDLE_ENV, henv);
return 0;
}
行宽绑定(数组绑定)¶
此示例显示在使用行集大小为10的块游标时,使用行宽绑定方式(row-wise)提取行集的数据。
#include <string.h>
#include <sql.h>
#include <sqlext.h>
#include <sqltypes.h>
#include <odbcss.h>
#include <stdio.h>
#define MAXBUFLEN 255
#define ROW_ARRAY_SIZE 10
typedef struct tagUserStruct {
SQLINTEGER UserID;
SQLCHAR UserName[MAXBUFLEN];
SQLINTEGER UserIDInd;
SQLINTEGER UserNameInd;
} UserStruct;
UserStruct UserArray[ROW_ARRAY_SIZE];
SQLUINTEGER NumRowsFetched;
SQLUSMALLINT RowStatusArray[ROW_ARRAY_SIZE];
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_ROW_BIND_TYPE,
(SQLPOINTER)sizeof(UserStruct), 0);
// 绑定结果集
SQLBindCol(hstmt1, 1, SQL_C_SLONG, (SQLPOINTER)UserArray[0].UserID,
sizeof(UserArray[0].UserID),
(SQLINTEGER*)UserArray[0].UserIDInd);
SQLBindCol(hstmt1, 2, SQL_C_CHAR, UserArray[0].UserName,
sizeof(UserArray[0].UserName),
(SQLINTEGER*)UserArray[0].UserNameInd);
// 执行SQL语句
SQLExecDirect(hstmt1, (SQLCHAR*)"SELECT ID, USER_NAME FROM Users",
SQL_NTS);
// 调用一次SQLFetchScroll就可以获取行集的所有行
while ((retcode = SQLFetchScroll(hstmt1,SQL_FETCH_NEXT,0)) !=
SQL_NO_DATA)
{
for (int i = 0; i < NumRowsFetched; i ++)
{
// 根据行的状态决定获取的数据是否有效
if (RowStatusArray[i] != SQL_ROW_ERROR && RowStatusArray[i] !=
SQL_ROW_DELETED &&
RowStatusArray[i] != SQL_ROW_NOROW)
printf("User ID : %d, User Name : %sn", UserArray[i].UserID,
UserArray[i].UserName);
}
}
// Close the cursor.
SQLCloseCursor(hstmt1);
// 释放语句句柄
// 断开连接
// 释放连接句柄和环境句柄
SQLFreeHandle(SQL_HANDLE_STMT, hstmt1);
SQLDisconnect(hdbc1);
SQLFreeHandle(SQL_HANDLE_DBC, hdbc1);
SQLFreeHandle(SQL_HANDLE_ENV, henv);
return 0;
}