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

Именованные курсоры

< Лекция 7 || Лекция 8: 12 || Лекция 9 >
Аннотация: Описывается применение именованного курсора, рассматривается механизм асинхронного выполнения функций

Создание именованного курсора

Курсор, для которого определено имя, называется именованным курсором.

Ассоциировать имя курсора с активным дескриптором оператора можно вызовом функции SQLSetCursorName. В том случае, если эта функция не вызывается явным образом, драйвер при необходимости может генерировать имя курсора при выполнении SQL-оператора.

Функция SQLSetCursorName имеет следующее формальное описание:

SQLRETURN SQLSetCursorName(
     SQLHSTMT      StatementHandle,
     SQLCHAR *     CursorName,
     SQLSMALLINT     NameLength);

Параметр StatementHandle ([Input]) указывает дескриптор оператора, а параметр CursorName ([Input]) задает назначаемое имя курсора. Отметим, что для эффективной обработки имя курсора не должно иметь лидирующих или завершающих пробелов.

Параметр NameLength ([Input]) определяет длину буфера *CursorName.

Следующий пример иллюстрирует применение функции SQLSetCursorName для получения имени курсора и выполнения затем позиционированного SQL-оператора UPDATE:

#define NAME_LEN 40
#define PHONE_LEN 12

SQLHSTMT     hstmtSelect;  // Дескриптор оператора
                           // (для оператора SELECT)
SQLHSTMT     hstmtUpdate;  // Дескриптор оператора
                           // (для оператора UPDATE)
SQLRETURN    retcode;
SQLHDBC      hdbc;
SQLCHAR      szName[NAME_LEN], szPhone[PHONE_LEN];
SQLINTEGER   cbName, cbPhone;

/* Создаем дескриптор оператора и определяем имя курсора */
SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmtSelect);
SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmtUpdate);
SQLSetCursorName(hstmtSelect, "C1", SQL_NTS);

/* Выполняем SQL-оператор SELECT для формирования результирующего набора 
   и связываем его столбцы с локальными буферами для извлечения данных */
SQLExecDirect(hstmtSelect,
      "SELECT NAME, PHONE FROM Tbl1", SQL_NTS);
SQLBindCol(hstmtSelect, 1, SQL_C_CHAR, 
           szName, NAME_LEN, &cbName);
SQLBindCol(hstmtSelect, 2, SQL_C_CHAR,
           szPhone, PHONE_LEN, &cbPhone);

/* Выбираем строки результирующего набора до тех пор, 
   пока не найдем строку "Иванов А." */
do
 retcode = SQLFetch(hstmtSelect);
while ((retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO) &&
   (strcmp(szName, "Иванов А.") != 0));

/* Выполняем позиционированный UPDATE для текущей выбранной строки 
   именованного курсора */
if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO) {
   SQLExecDirect(hstmtUpdate,
   "UPDATE Tbl2 SET PHONE=\"1373737\"
    WHERE CURRENT OF C1", SQL_NTS);
}

Для получения имени курсора, ассоциированного с конкретным дескриптором оператора, используется функция SQLGetCursorName, которая имеет следующее формальное описание:

SQLRETURN SQLGetCursorName(
     SQLHSTMT     StatementHandle,
     SQLCHAR *     CursorName,
     SQLSMALLINT     BufferLength,
     SQLSMALLINT *     NameLengthPtr);

Параметр StatementHandle ([Input]) указывает дескриптор оператора.

Имя курсора возвращается в буфере, определяемом параметром CursorName ([Output]).

Параметр BufferLength ([Input]) задает длину буфера *CursorName в байтах. Параметр NameLengthPtr ([Output]) определяет число байтов (включая ограничивающий 0-символ), которые занимает имя курсора. Если размер выделенного буфера меньше, чем требуется под имя курсора, то возвращаемое имя усекается.

В том случае, если в приложении функция SQLSetCursorName для задания имени курсора не вызывается, то драйвер автоматически генерирует имя курсора, начинающееся с префикса SQL_CUR.

Имя курсора в основном используется для позиционированного изменения или удаления, которое указывается в SQL-операторе фразой WHERE CURRENT OF имя_курсора.

Отметим, что в ODBC 2.x в том случае, если курсор не был открыт и ему не было назначено имя при вызове функции SQLSetCursorName, то инициировалась ошибка с кодом ответа SQLSTATE HY015 (Нет имени курсора). В версии ODBC 3.x вне зависимости от того, вызывалась ли функция SQLSetCursorName, драйвер всегда возвращает имя курсора.

Пока курсор не открыт, разрешено его переименование. Для этого достаточно вызвать функцию SQLSetCursorName.

Явно или неявно созданное имя курсора остается установленным до тех пор, пока не будет разрушен дескриптор оператора при вызове функции SQLFreeHandle с параметром HandleType, равным SQL_HANDLE_STMT.

Свойства курсора

Свойства курсора устанавливаются посредством атрибутов оператора. Для определения атрибутов оператора используется функция SQLSetStmtAttr, которая имеет следующее формальное описание:

SQLRETURN SQLSetStmtAttr(
     SQLHSTMT     StatementHandle,
     SQLINTEGER     Attribute,
     SQLPOINTER     ValuePtr,
     SQLINTEGER     StringLength);

Параметр StatementHandle ([Input]) указывает дескриптор оператора, для которого устанавливается значение атрибута оператора. Параметр Attribute ([Input]) определяет атрибут, значение которого задается параметром ValuePtr ([Input]). В зависимости от типа устанавливаемого атрибута параметр ValuePtr может быть: 32-битовым беззнаковым целым значением; указателем на null-ограниченную строку символов или двоичный буфер; значением, определяемым драйвером.

Параметр StringLength ([Input]) в зависимости от типа параметра может: игнорироваться (для целочисленных значений); указывать длину строки или быть равным SQL_NTS для null-ограниченных строк; быть равным результату макроса SQL_LEN_BINARY_ATTR (length) для указателя на двоичный буфер; для ValuePtr, который является указателем на значение, отличное от null-ограниченной строки или двоичного буфера, параметр должен быть равен SQL_IS_POINTER ; для значений фиксированной длины параметр может быть равен SQL_IS_INTEGER или SQL_IS_UINTEGER.

< Лекция 7 || Лекция 8: 12 || Лекция 9 >
Евгений Снегиренко
Евгений Снегиренко
Россия, г. Кемерово