Связывание по строкам
При использовании связывания по строкам определяется структура, содержащая от одного до трех элементов для каждого столбца извлекаемых данных. Первый элемент предназначается для извлекаемых данных, второй - для длины / индикатора буфера, третий - для индикатора буфера при раздельном сохранении значений длины и индикатора (что определяется дескрипторами полей SQL_DESC_INDICATOR_PTR и SQL_DESC_OCTET_LENGTH_PTR).
Массив таких структур должен содержать количество элементов, равное числу строк в извлекаемом наборе строк.
Размер структуры (число строк) указывается атрибутом оператора SQL_ATTR_ROW_BIND_TYPE. При связывании используются адреса каждого члена первого элемента массива. Так, адрес конкретного значения из набора строк может быть вычислен следующим образом (нумерация строк с 1):
Адрес = Адрес_связывания + ((Номер_строки - 1) * Размер_структуры)
На следующем рисунке приведена схема связывания по строкам.
Следующий пример иллюстрирует применение связывания по строкам для набора строк, состоящего из трех столбцов.
#define ROW_ARRAY_SIZE 10
// Определяем структуру TBL_INFO и создаем массив // структур, содержащий 10 элементов typedef struct { SQLUINTEGER ID1; // Для значения 1 столбца SQLINTEGER ID1Ind; // Для длины/индикатора SQLCHAR Sal[11]; // Для значения 2 столбца SQLINTEGER SalLenOrInd; SQLCHAR Status[7]; // Для значения 3 столбца SQLINTEGER StatusLenOrInd; } ORDERINFO; TBL_INFO TBL_Array[ROW_ARRAY_SIZE]; // Массив структур
SQLUINTEGER NumRowsFetched; SQLUSMALLINT RowStatusArray[ROW_ARRAY_SIZE], i; SQLRETURN rc; SQLHSTMT hstmt;
// Определяем размер структуры, используя атрибут //оператора SQL_ATTR_ROW_BIND_TYPE, и одновременно // устанавливаем тип связывания по строкам SQLSetStmtAttr(hstmt, SQL_ATTR_ROW_BIND_TYPE, sizeof(TBL_INFO), 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 для указания на // NumRowsFetched SQLSetStmtAttr(hstmt, SQL_ATTR_ROWS_FETCHED_PTR, &NumRowsFetched, 0);
// Связываем поля структуры первого элемента массива // со столбцами ID1, Sal и Status SQLBindCol(hstmt, 1, SQL_C_ULONG, &TBL_Array[0].ID1, 0, &TBL_Array[0].ID1Ind); SQLBindCol(hstmt, 2, SQL_C_CHAR, TBL_Array[0].Sal, sizeof(TBL_Array[0].Sal), &TBL_Array[0].SalLenOrInd); SQLBindCol(hstmt, 3, SQL_C_CHAR, TBL_Array[0].Status, sizeof(TBL_Array[0].Status), &TBL_Array[0].StatusLenOrInd);
// Выполняем SQL-оператор SELECT для формирования // результирующего набора SQLExecDirect(hstmt, "SELECT ID1, Sal, Status FROM TBL1", SQL_NTS);
// Используя блочный курсор, извлекаем установленное //число строк while ((rc = SQLFetchScroll(hstmt,SQL_FETCH_NEXT,0)) != SQL_NO_DATA) { // Переменная NumRowsFetched содержит число // в действительности извлеченных строк for (i = 0; i < NumRowsFetched; i++) { if (RowStatusArray[i] == SQL_ROW_SUCCESS|| RowStatusArray[i] == SQL_ROW_SUCCESS_WITH_INFO) { if (TBL_Array[i].ID1Ind == SQL_NULL_DATA) std::cout<<" NULL "; else std::cout<< TBL_Array[i].ID1; if (TBL_Array[i].SalLenOrInd == SQL_NULL_DATA) std::cout<< " NULL "; else std::cout<< TBL_Array[i].Sal; if (TBL_Array[i].StatusLenOrInd == SQL_NULL_DATA) std::cout<< " NULL\n"; else std::cout<< TBL_Array[i].Status; } } } // Закрываем курсор SQLCloseCursor(hstmt);