Параметрические запросы
Передача параметров
Если перед выполнением функции SQLExecDirect значения параметров, используемых в запросе, не переданы на сервер, то функция возвращает код ответа SQL_NEED_DATA. Для передачи параметров в приложении могут использоваться функции SQLParamData и SQLPutData. Функция SQLParamData используется совместно с функцией SQLPutData для передачи значений параметров во время выполнения. Если функция SQLParamData возвращает значение SQL_NEED_DATA, то она также возвращает и номер параметра, для которого следует ввести значение. Передача значения параметра выполняется функцией SQLPutData.
Функция SQLParamData имеет следующее формальное описание:
SQLRETURN SQLParamData( SQLHSTMT StatementHandle, SQLPOINTER * ValuePtrPtr);
Параметр StatementHandle ([Input]) указывает дескриптор оператора, а параметр ValuePtrPtr ([Output]) указывает буфер, который был предназначен для хранения параметра функцией SQLBindParameter (указывается как значение параметра ParameterValuePtr ).
Функция SQLPutData позволяет приложению передавать данные параметра или столбца во время выполнения. При этом данные могут передаваться по частям.
Функция SQLPutData имеет следующее формальное описание:
SQLRETURN SQLPutData( SQLHSTMT StatementHandle, SQLPOINTER DataPtr, SQLINTEGER StrLen_or_Ind);
Параметр StatementHandle ([Input]) указывает дескриптор оператора, параметр DataPtr ([Input]) определяет указатель буфера, в котором размещается значение параметра или столбец (значение соответствующего C-типа, указанного параметром ValueType функции SQLBindParameter или параметром TargetType функции SQLBindCol ), а параметр StrLen_or_Ind ([Input]) определяет длину передаваемых данных *DataPtr.
Следующий пример иллюстрирует применение функций OBDC API для передачи параметров, используемых оператором INSERT. Этот оператор содержит два параметра - для полей F1_ID и F2_PIC. Для каждого параметра приложение вызывает метод SQLBindParameter, определяющий С-тип данных и SQL-тип поля.
#define MAX_DATA_LEN 1024 SQLINTEGER cbF1_ID = 0, cbF2_PICParam, cbData; SQLUINTEGER sF1_ID; szPhotoFile; SQLPOINTER pToken, InitValue; SQLCHAR Data[MAX_DATA_LEN]; SQLRETURN retcode; SQLHSTMT hstmt; // Компиляция параметрического запроса retcode = SQLPrepare(hstmt, "INSERT INTO TBL1 (F1_ID, F2_PIC) VALUES (?, ?)", SQL_NTS); if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO) { // Выполнение связывания параметров. // Для 2 параметра передаем в ParameterValuePtr // вместо адреса буфера номер параметра SQLBindParameter(hstmt, 1, // Для 1 параметра SQL_PARAM_INPUT, SQL_C_ULONG, SQL_INTEGER, 0, 0, &sF1_ID, 0, &cbF1_ID); SQLBindParameter(hstmt, 2, // Для 2 параметра SQL_PARAM_INPUT, SQL_C_BINARY, SQL_LONGVARBINARY, 0, 0, (SQLPOINTER) 2, // Передаваемый номер 0, &cbF2_PICParam); // Значения второго параметра будут передаваться // во время выполнения. // Длина параметра в макросе SQL_LEN_DATA_AT_EXEC // равна 0. Это предполагает, что драйвер вернет // значение "N" для типа SQL_NEED_LONG_DATA_LEN, // указанного в функции SQLGetInfo. cbF2_PICParam = SQL_LEN_DATA_AT_EXEC(0); sF1_ID = MyGetNextID(); /* Запрос следующего значения поля F1_ID таблицы TBL1 */ retcode = SQLExecute(hstmt); /* Для параметров времени выполнения (data-at-execution parameters) вызывается функция SQLParamData для получения номера параметра, установленного функцией SQLBindParameter. */ /* Вспомогательные функции MyInitData и MyGetData формируют значение параметра*/ /* Функция SQLParamData завершает процесс обработки параметра */ while (retcode == SQL_NEED_DATA) { retcode = SQLParamData(hstmt, &pToken); // Запрос // значений параметров во время выполнения if (retcode == SQL_NEED_DATA) { MyInitData((SQLSMALLINT)pToken, InitValue); while (MyGetData(InitValue, (SQLSMALLINT)pToken, Data, &cbData)) SQLPutData(hstmt, Data, cbData); } } } VOID MyInitData (sParam, InitValue) SQLPOINTER InitValue; { SQLCHAR szPhotoFile[MAX_FILE_NAME_LEN]; /* Запрос у пользователя имени используемого BMP-файла, открытие этого файла и возвращения дескриптора файла */ MyPromptPhotoFileName(szPhotoFile); MyOpenBMPFile(szPhotoFile, (FILE *)InitValue); break; } BOOL MyGetData (InitValue, sParam, Data, cbData) SQLPOINTER InitValue; SQLCHAR * Data; SQLINTEGER * cbData; BOOL Done; { /* Функция MyGetNextBMPData возвращает следующую часть данных и количество передаваемых байтов (не более, чем MAX_DATA_LEN). */ Done = MyGetNextBMPData((FILE *)InitValue, Data, MAX_DATA_LEN, &cbData); if (Done) { MyCloseBMPFile((FILE *)InitValue); return (TRUE); } return (FALSE); }
Массивы параметров
Если значение атрибута дескриптора оператора SQL_ATTR_PARAMSET_SIZE больше 1 и SQL-оператор имеет хотя бы один маркер параметра, то функция SQLExecDirect будет выполняться последовательно для каждого значения параметра из массива, указанного параметром ParameterValuePointer функции SQLBindParameter.