Параметры могут использоваться как при непосредственном, так и при подготавливаемом выполнении. Маркеры параметров определяются в SQL – операторах с помощью символа ‘?’. Например: select * from staff where position = ? или insert into staff (fname, lname, position) values (?, ?, ?). Маркеры параметров необходимо связать с областью хранения, из которой во время выполнения выбирается значение параметра. Чтобы связать параметры прикладная программа вызывает функцию SQLBindParameter(). Эта функция связывает буфер с маркером параметра в SQL – операторе.
RETCODE SQLBindParameter(hstmt, ipar, fParamType, fCType, fSqlType, cbColDef, ibScale, rgbValue, cbValueMax, pcbValue)
Таблица 14 Параметры функции SQLBindParameter()
Тип | Аргумент | Использование | Описание |
HSTMT | hstmt | Вход | Идентификатор оператора |
UWORD | ipar | Вход | Номер параметра, упорядоченный слева направо. Нумерация начинается с 1. |
SWORD | fParamType | Вход | Тип параметра. Может принимать одно из следующих значений: SQL_PARAM_INPUT, SQL_PARAM_OUTPUT, SQL_PARAM_INPUT_OUTPUT |
SWORD | fCType | Вход | C – тип данных параметра. Некоторые из возможных значений: SQL_C_BINARY, SQL_C_BIT, SQL_C_CHAR, SQL_C_DOUBLE, SQL_C_FLOAT, SQL_C_SLONG, SQL_C_SSHORT, SQL_C_ULONG, SQL_C_USHORT, SQL_C_DEFAULT – - определяет, что значение параметра было передано из С – типа данных по умолчанию в SQL – тип данных, определенный в fSqlType. |
Продолжение таблицы 14
SWORD | fSqlType | Вход | SQL – тип данных параметра. Некоторые из возможных значений: SQL_BIGINT, SQL_BINARY, SQL_BIT, SQL_CHAR, SQL_DATE, SQL_DOUBLE, SQL_FLOAT, SQL_INTEGER, SQL_LONGVARCHAR, SQL_VARCHAR. |
UDWORD | cbColDef | Вход | Точность столбца или выражения соответствующего маркера параметра |
SWORD | ibScale | Вход | Размер столбца или выражения соответствующего маркера параметра |
PTR | rgbValue | Вход/Выход | Указатель буфера для данных параметра, который при вызове SQLExecute() или SQLExecDirect() содержит действительные значения параметра |
SDWORD | cbValueMax | Вход | Максимальная длина буфера |
SDWORD* | pcbValue | Вход/Выход | Указатель буфера для длины параметра |
В данной функции fCType – тип данных, из которых происходит конвертирование, fSqlType – тип данных в которые происходит конвертирование, и он должен совпадать с SQL – типом столбца, соответствующего этому параметрическому маркеру. SQL – тип данных столбца может быть получен с помощью SQLColumns(), cbColDef и ibScale являются точностью и размером столбца источника данных, информация о которых тоже может быть получена посредством SQLColumns(). Если fSqlType этого параметра является SQL_LONGVARBINARY или SQL_LONGVARCHAR, то cbColDef должен содержать длину значения параметра, который посылается вместо соответствующего столбца. Параметр rgbValue может быть либо параметром ввода, либо вывода, либо ввода – вывода в зависимости от значения в fParamType. Параметр cbValueMax используется только тогда, когда тип параметра является двоичным или символьным. В этом случае он определяет длину буфера rgbValue. Для типов фиксированной длины он игнорируется и вместо него используется длина С – типа данных. Параметр pcbValue – указатель буфера, в котором может содержаться одно из следующих значений: длина значения параметра в rgbValue, SQL_NTS, SQL_NULL_DATA, SQL_DATA_AT_EXEC или SQL_DEFAULT_PARAM. Если pcbValue определяет длину значения параметра, то он применяется только в случае, если тип параметра в fCType является двоичным или символьным. Для типов фиксированной длины он игнорируется (хотя и должен быть определен). SQL_DATA_AT_EXEC используется при передаче параметров во время выполнения. SQL_DEFAULT_PARAM применяется только при использовании процедур, сообщая процедуре, что лучше использовать значение по умолчанию.
Для параметров, определяемых во время выполнения два аргумента функции SQLBindParameter() используются иначе, чем было описано ранее. Вместо передачи длины параметра в pcbValue, посылается значение SQL_DATA_AT_EXEC, что сообщает драйверу, что данные для маркера будут переданы во время выполнения оператора. Аргумент rgbValue также используется иначе, а именно вместо указания на связываемый буфер, он устанавливается в определенное прикладной программой значение, идентифицирующее параметр (например его номер). Данное значение должно быть сохранено в программе, так как именно оно будет возвращаться при вызове SQLParamData(), сообщая программе какой именно параметр запрашивает данные. Описание параметров SQLParamData() приведено в таблице 14. Как и любая функция ODBC эта функция возвращает данные типа RETCODE.
Таблица 15 Описание параметров SQLParamData()
Тип | Аргумент | Использование | Описание |
HSTMT | hstmt | Вход | Идентификатор оператора |
PTR | prgbValue | Выход | Указатель области хранения в памяти значения, которое было определено для аргумента rgbValue (идентификатор параметра требующего данные) в SQLBindParameter() (для значений параметров) или адрес буфера rgbValue, определенный в SQLBindCol() (для значений выбираемых столбцов результирующего множества). |
Как только параметр, определяемый во время выполнения, будет связан, прикладная программа может выполнить SQL – оператор. Кодом возврата функции выполнения (SQLExecute() или SQLExecDirect()) будет SQL_NEED_DATA. Затем прикладная программа предоставляет необходимые данные с помощью функции SQLParamData() и SQLPutData().
Функция SQLPutData() позволяет передавать данные в качестве значений параметров во время выполнения оператора. Функция использует следующие аргументы:
Таблица 16 Описание параметров SQLPutData()
Тип | Аргумент | Использование | Описание |
HSTMT | hstmt | Вход | Идентификатор оператора |
PTR | rgbValue | Вход | Указатель области хранения в памяти значений параметра или столбца. Данные должны использовать С – тип данных, определенный в аргументе fCType функции SQLBindParameter() (для параметров) или SQLBindCol() (для столбцов результата) |
SDWORD | cbValue | Вход | Определяет объём посылаемых данных. Объём данных может варьироваться от вызова к вызову для данного параметра или столбца. |
Сначала посредством rgbValue функция SQLBindParameter() идентифицирует параметр, для которого передаются данные. Например, если необходимо передавать значения двум параметрам, используя rgbValue можно установить значение 1 для первого параметра (его номер), а для второго установить значение 2. Если следующий за выполнением опреатора вызов SQLParamData() возвращает SQL_NEED_DATA, то в prgbValue возвращается указатель на параметр, требующий пересылки данных. По данному адресу возвращается идентификатор (номер) параметра, определенный посредством SQLBindParameter(). Требуемые данные затем посылаются порциями посредством SQLPutData(). После передачи последней порции данных необходимо сделать “контрольный” вызов SQLParamData(), чтобы проинформировать драйвер о последней порции данных для текущего параметра. Вызов SQLParamData() может вернуть номер следующего параметра оператора требующего данных. Вызовы SQLPutData() передают необходимые данные до последней порции. Если больше параметров требующих данных во время выполнения нет, то “контрольный” вызов SQLParamData() возвращает SQL_SUCCESS. На этом цикл передачи значений параметров заканчивается. В последующем примере демонстрируется возможности функций SQLBindParameter(), SQLParamData() и SQLPutData().
RETCODE UpdateBigCols (HSTMT hstmt)
{
RETCODE rc;
SDWORD cbDataLen;
// Подготовка оператора
rc=SQLPrepare(hstmt, “insert into MEMOTABLE (MEMCOL,
PICTURECOL) values (?, ?)”, SQL_NTS);
// Связывание параметров. Аргумент rgbValue определяет номер параметра
if (RETCODE_IS_SUCCESSFULL(rc))
{
rc=SQLBindParameter (hstmt, 1, SQL_PARAM_INPUT,
SQL_C_CHAR, SQL_LONGVARCHAR, 100000, 0,
(SDWORD) 1, 0, &cbDataLen);
}
if (RETCODE_IS_SUCCESSFULL(rc))
{
rc=SQLBindParameter (hstmt, 2, SQL_PARAM_INPUT,
SQL_C_BINARY, SQL_LONGVARBINARY, 100000, 0,
(SDWORD) 2, 0, &cbDataLen);
}
cbDataLen=SQL_DATA_AT_EXEC;
if (RETCODE_IS_SUCCESSFULL(rc))
{
rc=SQLExecute(hstmt);
}
//Загрузка данными
while (rc= = SQL_NEED_DATA)
{
SDWORD iWhatParam;
UCHAR rgbData[500];
SDWORD cbData;
rc=SQLParamData (hstmt, &iWhatParam);
if (rc= = SQL_NEED_DATA)
{
switch (iWhatParam)
case 1: do
{
GetMemoData(rgbData, cbData, sizeof (rgbData));
if (cbData!=0)
{
SQLPutData(hstmt, rgbData, cbData);
}
}
while (cbData!=0);
break;
case 2: do
{
GetPictData(rgbData, cbData, sizeof (rgbData));
if (cbData!=0)
{
SQLPutData(hstmt, rgbData, cbData);
}
}
while (cbData!=0);
}
}
}
В приведенном примере предполагаются имеющимися функции пользовательские функции GetMemoData() и GetPictData(), размещающие порции данных в массиве rgbData, а cbData определяет количество оставшейся информации.
Выборка результатов
Большинство описанных выше функций генерируют результат. Результат может быть либо результирующим множеством, либо числом строк на которые воздействовал оператор.
Результирующее множество представляет собой набор строк и столбцов, которые были определены SQL – оператором или функцией каталога.
После создания, результирующее множество, тем не менее располагается на сервере базы данных и требует извлечения прикладной программой клиента. Продвижение по строкам результирующего множества возможно посредством курсора. Курсор отмечает текущую позицию в результирующем множестве. Продвижение в пределах результирующего множества выполняется относительно позиции курсора.
Курсор автоматически генерируется для каждого результирующего множества. Непосредственно после создания результирующего множества, курсор устанавливается перед первой строкой данных. Для продвижения курсора следует вызывать функцию SQLFetch(). Данная функция продвигает курсор вперед на одну строку до тех пор, пока он не будет установлен за последней строкой результирующего множества.