Основы проектирования приложений баз данных

       

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


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

Ассоциировать имя курсора с активным дескриптором оператора можно вызовом функции 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.


Содержание раздела