Непосредственное выполнение целесообразно использовать в следующих случаях:
• SQL – операторы, которые должны быть выполнены, выполняются только один раз;
• не требуется информация о результирующем множестве до выполнения оператора.
Непосредственное выполнение реализуется с помощью функции SQLExecDirect() и представляет наиболее быстрый способ запуска SQL – оператора при одноразовом выполнении.
Синтаксис функции имеет вид:
RETCODE SQLExecDirect( hstmt, szSqlStr, sbSqlStr)
Таблица 28 Описание параметров SQLExecDirect()
Тип
Аргумент
Использование
Описание
HSTMT
hstmt
Вход
Идентификатор оператора
UCHAR*
szSqlStr
Вход
SQL – оператор для выполнения
SDWORD
sbSqlStr
Вход
Длина szSqlStr или SQL_NTS
Например, следующий вызов функции непосредственного выполнения будет возвращать все строки из таблицы STAFF:
rc=SQLExecDirect (hstmt, “select * from staff”, SQL_NTS).
Данный способ выполнения оператора предпочтителен в случае, если оператор предполагается выполнять несколько раз и требуется предварительная информация о результирующем множестве. Для подготавливаемого выполнения необходимы две функции: SQLPrepare() и SQLExecute().
SQLPrepare() подготавливает SQL – строку для выполнения. Синтаксис её ничем не отличается от синтаксиса SQLExecDirect(). Синтаксис SQLExecute() следующий:
RETCODE SQLExecute (hsmt)
где HSMT – предварительно назначенный идентификатор оператора.
SQLPrepare() отличается от SQLExecDirect() тем, что при вызове SQLPrepare() оператор на самом деле не выполняется. Вместо этого определяется путь доступа к данным и информация о результирующем множестве становится доступной для использования. Так функции SQLNumResultCols() и SQLRowCount() при вызове возвращают количество столбцов и строк результирующего множества. Так как план выполнения оператора после его подготовки известен, то его выполнение может выполняться несколько быстрее, чем при использовании SQLExecDirect(). Кроме того, каждый вызов SQLExecute() передает базе данных только идентификатор, а не строку запроса, что может несколько снизить сетевой трафик.
Параметры могут использоваться как при непосредственном, так и при подготавливаемом выполнении. Маркеры параметров определяются в SQL – операторах с помощью символа ‘?’. Например: select * from staff where position = ? или insert into staff (fname, lname, position) values (?, ?, ?). Маркеры параметров необходимо связать с областью хранения, из которой во время выполнения выбирается значение параметра. Чтобы связать параметры прикладная программа вызывает функцию SQLBindParameter(). Эта функция связывает буфер с маркером параметра в SQL – операторе.
Номер параметра,
упорядоченный слева направо. Нумерация начинается с 1.
SWORD
fParamType
Вход
Тип параметра. Может принимать одно из следующих значений:
SQL_PARAM_INPUT,
SQL_PARAM_OUTPUT,
SQL_PARAM_INPUT_OUTPUT
Продолжение таблицы 29
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.
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
Вход
Размер столбца или выражения соответствующего маркера параметра
Продолжение таблицы 29
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() приведено в таблице 30. Как и любая функция ODBC эта функция возвращает данные типа RETCODE.
Таблица 30 Описание параметров SQLParamData()
Тип
Аргумент
Использование
Описание
HSTMT
hstmt
Вход
Идентификатор оператора
PTR
prgbValue
Выход
Указатель области хранения в памяти значения, которое было определено для аргумента rgbValue (идентификатор параметра требующего данные) в SQLBindParameter() (для значений параметров) или адрес буфера rgbValue, определенный в SQLBindCol() (для значений выбираемых столбцов результирующего множества).
Как только параметр, определяемый во время выполнения, будет связан, прикладная программа может выполнить SQL – оператор. Кодом возврата функции выполнения (SQLExecute() или SQLExecDirect()) будет SQL_NEED_DATA. Затем прикладная программа предоставляет необходимые данные с помощью функции SQLParamData() и SQLPutData().
Функция SQLPutData() позволяет передавать данные в качестве значений параметров во время выполнения оператора. Функция использует следующие аргументы:
Таблица 31 Описание параметров 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 определяет количество оставшейся информации.