Московский государственный университет имени М.В.Ломоносова
Опубликован: 20.12.2005 | Доступ: свободный | Студентов: 3142 / 371 | Оценка: 4.22 / 3.86 | Длительность: 12:03:00
ISBN: 978-5-9556-0068-0
Лекция 6:

Применение курсоров

< Лекция 5 || Лекция 6: 1234 || Лекция 7 >

Выполнение множественных операций

Множественная операция выполняется функцией 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;
      }
   }
}
< Лекция 5 || Лекция 6: 1234 || Лекция 7 >