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

Блочная выборка данных

< Лекция 6 || Лекция 7: 123 || Лекция 8 >

Связывание столбцов, используемых с блочным курсором

При использовании блочного курсора за один вызов функции может возвращаться несколько строк. Поэтому с каждым столбцом должна связываться не просто переменная соответствующего типа, а массив. Такой массив обычно называется буфером набора строк (rowset buffer).

Возможно два типа связывания:

  • связывание по столбцу (column-wise binding), при котором с каждым столбцом связывается отдельный массив (структура данных, содержащая элементы одного типа);
  • связывание по строке (row-wise binding), при котором с каждой строкой связывается отдельный массив (структура данных, типы элементов которой соответствуют типам столбцов строки набора данных).

Для выполнения любого типа связывания используется функция ODBC API SQLBindCol. При этом тип связывания определяется атрибутом SQL_ATTR_ROW_BIND_TYPE. В случае использования блочного курсора со связыванием по строке или по столбцу, функции SQLBindCol в качестве параметра вместо адреса простой переменной передается адрес массива.

Связывание по столбцу

При использовании связывания по столбцу с каждым столбцом может быть связано от одного до трех массивов: первый массив - для извлекаемых значений, второй - для длины / индикатора буферов, третий - для индикатора буферов (если индикаторы и длина хранятся по отдельности). Каждый массив должен содержать число элементов, равное числу строк в извлекаемом наборе строк.

Хранятся ли по отдельности индикаторы и значения длины, определяется установкой дескрипторов полей SQL_DESC_INDICATOR_PTR и SQL_DESC_OCTET_LENGTH_PTR.

На следующем рисунке приведена схема связывания по столбцам.


Следующий пример иллюстрирует применение связывания по столбцам для набора строк, состоящего из трех столбцов:

#define ROW_ARRAY_SIZE 10  	// Кол-во строк 
                           	// в наборе строк

SQLUINTEGER    ID1Array[ROW_ARRAY_SIZE], 
               NumRowsFetched;
SQLCHAR        SalArray[ROW_ARRAY_SIZE][11],
               StatusArray[ROW_ARRAY_SIZE][7];
SQLINTEGER     ID1IndArray[ROW_ARRAY_SIZE],
               SalLenOrIndArray[ROW_ARRAY_SIZE],
               StatusLenOrIndArray[ROW_ARRAY_SIZE];
SQLUSMALLINT   RowStatusArray[ROW_ARRAY_SIZE], i;
SQLRETURN      rc;
SQLHSTMT       hstmt;

// Устанавливаем атрибут оператора // SQL_ATTR_ROW_BIND_TYPE для использования связывания 
// по столбцам
SQLSetStmtAttr(hstmt, SQL_ATTR_ROW_BIND_TYPE, 
                      SQL_BIND_BY_COLUMN, 0);
// Размер набора строк задаем атрибутом оператора 
// SQL_ATTR_ROW_ARRAY_SIZE 
SQLSetStmtAttr(hstmt, SQL_ATTR_ROW_ARRAY_SIZE, 
                      ROW_ARRAY_SIZE, 0);
// Устанавливаем атрибут оператора 
// SQL_ATTR_ROW_STATUS_PTR для определения массива 
// состояний строк
SQLSetStmtAttr(hstmt, SQL_ATTR_ROW_STATUS_PTR, 
                      RowStatusArray, 0);
// Устанавливаем атрибут оператора 
// SQL_ATTR_ROWS_FETCHED_PTR для указания на 
// cRowsFetched
SQLSetStmtAttr(hstmt, SQL_ATTR_ROWS_FETCHED_PTR, 
                      &NumRowsFetched, 0);

// Связываем массивы со столбцами ID1, Sal и Status
SQLBindCol(hstmt, 1, SQL_C_ULONG, 
           ID1Array, 0, 
           ID1IndArray);
SQLBindCol(hstmt, 2, SQL_C_CHAR, 
           SalArray, 
           sizeof(SalArray[0]),
            SalLenOrIndArray);
SQLBindCol(hstmt, 3, SQL_C_CHAR, 
           StatusArray, 
           sizeof(StatusArray[0]),
           StatusLenOrIndArray);

// Выполняем SQL-оператор SELECT для создания 
// результирующего набора
SQLExecDirect(hstmt, 
              "SELECT ID1, Sal, Status FROM TBL1", 
              SQL_NTS);

// Выполняем блочную выборку из результирующего набора
// В переменной NumRowsFetched возвращается число 
// в действительности выбранных строк
while ((rc = SQLFetchScroll(hstmt,SQL_FETCH_NEXT,0)) 
                                   != SQL_NO_DATA) 
{
   for (i = 0; i < NumRowsFetched; i++) {

// Отображаем только успешно извлеченные строки (если 
// код ответа (rc) равен SQL_SUCCESS_WITH_INFO или
// SQL_ERROR, то строку не выводим.)

      if ((RowStatusArray[i] == SQL_ROW_SUCCESS) ||
     (RowStatusArray[i] == SQL_ROW_SUCCESS_WITH_INFO))
{
         if (ID1IndArray[i] == SQL_NULL_DATA)
                       printf(" NULL      ");
         else          printf("%d\t", ID1Array[i]);
         if (SalLenOrIndArray[i] == SQL_NULL_DATA)
                       printf(" NULL      ");
         else          printf("%s\t", SalArray[i]);
         if (StatusLenOrIndArray[i] == SQL_NULL_DATA)
                       printf(" NULL\n");
         else          printf("%s\n", StatusArray[i]);
      }
   }
}
// Закрываем курсор
SQLCloseCursor(hstmt);
< Лекция 6 || Лекция 7: 123 || Лекция 8 >