Применение курсоров
Выполнение множественных операций
Множественная операция выполняется функцией SQLSetPos в том случае, если параметр RowNumber равен 0. Она выполняется для всех строк, у которых в массиве операций над строками установлено значение SQL_ROW_PROCEED.
По умолчанию должны обрабатываться все строки результирующего набора. Для того чтобы драйвер игнорировал одну или несколько строк, им в массиве операций над строками надо назначить значение SQL_ROW_IGNORE.
Это может быть выполнено вызовом функции SQLSetStmtAttr для установки атрибута оператора SQL_ATTR_ROW_OPERATION_PTR, указывающего на массив элементов типа SQLUSMALLINT. Это поле также может быть установлено вызовом функции SQLSetDescField для определения SQL_DESC_ARRAY_STATUS_PTR.
При множественных операциях игнорировать можно не только обработку строк, но и обработку столбцов (например, столбцов "только для чтения"). Для этого в функции SQLBindCol игнорируемый столбец следует пометить как SQL_COLUMN_IGNORE.
Следующий пример иллюстрирует применение функции SQLSetPos.
#define ROWS 20 // Число строк
// в результирующем наборе
#define STATUS_LEN 6
SQLCHAR szStatus[ROWS][STATUS_LEN], szReply[3];
SQLINTEGER cbStatus[ROWS], cbID;
SQLUSMALLINT rgfRowStatus[ROWS];
SQLUINTEGER sID, crow = ROWS, irow;
SQLHSTMT hstmtS, hstmtU;
SQLSetStmtAttr(hstmtS, SQL_ATTR_CONCURRENCY,
(SQLPOINTER) SQL_CONCUR_ROWVER, 0);
// Определение типа курсора
SQLSetStmtAttr(hstmtS, SQL_ATTR_CURSOR_TYPE,
(SQLPOINTER) SQL_CURSOR_KEYSET_DRIVEN, 0);
// Определение размера результирующего набора
SQLSetStmtAttr(hstmtS, SQL_ATTR_ROW_ARRAY_SIZE,
(SQLPOINTER) ROWS, 0);
// Определение массива состояния строк
SQLSetStmtAttr(hstmtS, SQL_ATTR_ROW_STATUS_PTR,
(SQLPOINTER) rgfRowStatus, 0);
SQLSetCursorName(hstmtS, "C1", SQL_NTS);
// Выполнение SQL-оператора
SQLExecDirect(hstmtS,
"SELECT ID1, STATUS FROM TBL1", SQL_NTS);
// Выполнение "связывания" данных
SQLBindCol(hstmtS, 1, SQL_C_ULONG, &sID, 0, &cbID);
SQLBindCol(hstmtS, 2, SQL_C_CHAR, szStatus,
STATUS_LEN, &cbStatus);
while ((retcode == SQLFetchScroll(hstmtS,
SQL_FETCH_NEXT, 0)) != SQL_ERROR)
{
if (retcode == SQL_NO_DATA_FOUND)
break;
// Отображение 20-ти извлеченных строк
// результирующего набора
for (irow = 0; irow < crow; irow++) {
if (rgfRowStatus[irow] != SQL_ROW_DELETED)
// Отображение данных
printf("%2d %5d %*s\n", irow+1, sID,
NAME_LEN-1, szStatus[irow]);
}
while (TRUE) {
printf("\nУкажите номер изменяемой строки или 0?");
gets(szReply); // Получаем номер строки
irow = atoi(szReply);
if (irow > 0 && irow <= crow) {
printf("\nНовое состояние?");
gets(szStatus[irow-1]); // Получаем новое
// значение для поля STATUS
// Изменяем текущую позицию курсора
SQLSetPos(hstmtS, irow, SQL_POSITION,
SQL_LOCK_NO_CHANGE);
SQLPrepare(hstmtU,
"UPDATE TBL1 SET STATUS=?
WHERE CURRENT OF C1", SQL_NTS);
// Выполняем "связывание" параметра
SQLBindParameter(hstmtU, 1, SQL_PARAM_INPUT,
SQL_C_CHAR, SQL_CHAR,
STATUS_LEN, 0,
szStatus[irow], 0, NULL);
// Выполняем изменение данных
SQLExecute(hstmtU);
} else if (irow == 0) {
break;
}
}
}
