СТАТЬИ > Уроки Iczelion'а

ODBC. Урок 3. Подготовка и Использование Инструкций

  На этой консультации, мы продолжим изучение приёмов программирования ODBC. Мы изучим, как взаимодействовать с источником данных через ODBC. Из предыдущей консультации мы рассмотрелив как осуществить подключение к источнику данных. Это - первый шаг. Подключение определяет путь данных между вами и источником данных. Это пассивно. Чтобы взаимодействовать с источником данных, вы должны использовать инструкции. Вы можете понимать эти инструкции как команды, которые вы посылаете источнику данных. "Команда" должна быть написана на SQL. Используя инструкции, вы можете изменить строение источника данных, сделать запрос для получения некоторых данных, модифицировать и удалить данные.

  Шаги для подготовки и использования инструкций следующие:

ВЫДЕЛЕНИЕ ПАМЯТИ ДЛЯ ОПЕРАТОРНОГО ИДЕНТИФИКАТОРА

  Вы выделяете память для операторного идентификатора вызывая SQLAllocHandle, передав ей соответствующие параметры.

  Например:

.data?
 hStmt dd ?
.code
      ......
      invoke SQLAllocHandle, SQL_HANDLE_STMT, hConn, addr hStmt

СОЗДАНИЕ SQL-ИНСТРУКЦИИ

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

ВЫПОЛНЕНИЕ ИНСТРУКЦИИ

  Имеются четыре пути выполнения инструкции, в зависимости от того, когда они откомпилированы и кто определяет их.

 
Немедленное выполнение Ваша программа определяет инструкцию SQL. Инструкция компилируется и исполняется во время выполнения за один шаг.
Подготовленное Выполнение Ваша программа также определяет инструкцию SQL. Однако, подготовка и выполнение разделены на два шага: сначала инструкция SQL компилируется, а затем она выполненяется. Используя этот метод, вы можете откомпилировать инструкцию SQL лишь однажды а затем выполнять ту же самую инструкцию SQL определённое число раз. Это экономит время.
Процедуры Инструкции SQL компилируются и сохраняются в источнике данных. Ваша программа вызывает их во время выполнения.
Каталог Инструкции SQL жестко закодированы в ODBC драйвер. Цель функций каталога - возвратить предопределенные наборы исхода, типа имен таблиц в базе данных. В целом, функции каталога используются, чтобы получить информацию относительно источника данных. Ваша программа вызывает их во время выполнения.

  Эти четыре метода имеют "за" и "против". Немедленное выполнение хорошо, когда вы выполняете специфическую инструкцию SQL только однажды. Если бы вы должны были выполнить инструкцию несколько раз последовательно, то вам лучше было бы использовать подготовленное выполнение, потому что инструкция SQL будет откомпилирована лишь однажды. В этом случае последовательное выполнение, будет быстрее, потому что инструкция уже откомпилирована. Процедуры - лучший выбор, если вы хотите оптимизации по скорости. Поскольку процедуры уже откомпилированы и сохранены в источнике данных, они выполняются довольно быстро. Плохо то, что не все данные поддерживают процедуры. Каталог - для получения информации относительно строения источника данных.

  На данной консультации, мы сосредоточимся на немедленном и подготовленном выполнении, потому что они выполняются на стороне нашего приложения. Запись процедур осуществляется в DBMS формате. Мы используем функции каталога в будущем.

  НЕМЕДЛЕННОЕ ВЫПОЛНЕНИЕ

  Чтобы выполнить вашу инструкцию SQL немедленно, вызовите функцию SQLEхесDirect, которая имеет следующий синтаксис:

SQLExecDirect proto StatementHandle:DWORD,
                    pStatementText:DWORD,
                    TextLength:DWORD

  Возможные возвращаемые значения:

 
SQL_SUCCESS Операция успешна.
SQL_SUCCESS_WITH_INFO Операция успешна, но может быть предупреждение.
SQL_ERRORОперация потерпела неудачу.
SQL_INVALID_HANDLEОператорный идентификатор , который вы передали функции, был недействителен.
SQL_NEED_DATAЕсли инструкция SQL включает один или большее количество параметров, и вы не сумели передать их ей перед выполнением, вы получите это возвращаемое значение. В этом случае вы должны представить параметры через SQLPARAMDATA или SQLPUTDATA.
SQL_NO_DATAЕсли ваша инструкция SQL не возвращает результата, то вы получите этот параметр. Если этот параметр получен, то ваша функция выполнена успешно но она не возвращает никаких результатов.
SQL_STILL_EXECUTINGЕсли вы выполняете инструкцию асинхронно, SQLExecDirect немедленно возвращает это значение, указывая, что инструкция обрабатывается. По умолчанию, ODBC драйверы работают в синхронном режиме, который является наилучшим, если вы используете параллельные процессы OS. Если вы хотите асинхронного выполнения, вы можете установить операторный атрибут с SQLSETSTMTATTR.

  Пример:

.data SQLStmt db "select * from Sales",0 .data? hStmt dd ? .code ..... invoke SQLAllocHandle, SQL_HANDLE_STMT, hConn, addr hStmt .if ax==SQL_SUCCESS || ax==SQL_SUCCESS_WITH_INFO invoke SQLExecDirect, hStmt, addr SQLStmt, sizeof SQLStmt

ПОДГОТОВЛЕННОЕ ВЫПОЛНЕНИЕ

  Процесс выполнения инструкции SQL разделен на две фазы. В первой фазе, вы должны подготовить инструкцию, вызывая SQLPrepare. Затем, вы вызываете SQLEXECUTE, чтобы фактически выполнить инструкцию. Используя подготовленное выполнение, вы можете исполнять с помощью SQLEXECUTE ту же самую инструкцию SQL любое число раз.

  SQLPrepare принимает те же самые три параметра, что и SQLExecDirect, так что я не буду показывать его определение здесь. SQLExecute имеет следующий синтаксис:

SQLExecute proto StatementHandle:DWORD

  Пример:

.data
 SQLStmt db "select * from Sales",0
.data?
 hStmt dd ?
.code
   .....
   invoke SQLAllocHandle, SQL_HANDLE_STMT, hConn, addr hStmt
    .if ax==SQL_SUCCESS || ax==SQL_SUCCESS_WITH_INFO 
       invoke SQLPrepare, hStmt, addr SQLStmt, sizeof SQLStmt
       invoke SQLExecute, hStmt

  Вы можете задаться вопросом, каково преимущество подготовленного выполнения по сравнению с немедленным выполнением. От вышеупомянутых примеров, это не очевидно. Мы должны знать кое что относительно операторных параметров, чтобы быть квалифицированными в оценке этого.

ОПЕРАТОРНЫЕ ПАРАМЕТРЫ

  Параметры, как упомянуто здесь, являются переменными, которые используются инструкциями SQL. Например, если мы имеем таблицу названную "служащие"(employee), которая имеет три поля: "имя"(name), "фамилия", и "Номер_телефона"(telephoneNo), и мы должны найти номер телефона служащего по имени Bob, то мы можем использовать следующую инструкцию SQL:

select telephoneNo from employee where name='Bob'

  Эта инструкция SQL будет работать так как мы хотим, но что, если мы хотим найти телефон другого служащего? Если вы не используете параметр, вы не имеете свободы выбора, но можно создать новую строку SQL и откомпилировать/выполнить её снова.

  Теперь скажем, что мы не можем допустить эту неэффективность. Мы можем использовать параметр в наших интересах. В нашем примере выше, мы должны заменить строку/значение?. Строка SQL будет:

select telephoneNo from employee where name=?

  Подумайте немного относительно этого: Как ODBC драйвер может знать то, какое значение он должен вставить вместо параметра? Ответ: мы должны снабдить его требуемым значением. Метод которым мы можем сделать это назван закреплением параметра. По сути, это - процесс соединения маркера параметра с переменной в вашем приложении. В вышеупомянутом примере, мы должны создать строковый буфер и затем сообщать ODBC драйверу, что, когда требуется действительное значение параметра, оно должно быть получено значение из строкового буфера, который мы снабдили значениями. Как только параметр связан с переменной, он будет продолжать быть связанным с этой переменной, пока не произойдёт связывания с другой переменной, или пока все параметры не будут лишены этой связи, вызовом SQLFreeStmt с SQL_RESET_PARAMS в качестве параметра.

  Вы связываете параметр с переменной, вызывая SQLBindParameter, который имеет следующий синтаксис:

SQLBindParameter proto StatementHandle:DWORD,
                       ParameterNumber:DWORD,
                       InputOutputType:DWORD,
                       ValueType:DWORD,
                       ParameterType:DWORD,
                       ColumnSize:DWORD,
                       DecimalDigits:DWORD,
                       ParameterValuePtr:DWORD,
                       BufferLength:DWORD,
                       pStrLenOrIndPtr:DWORD

  Вы конечно можете сказать, что очень много возможных значений для pStrLenOrIndPtr, но главным образом, мы будем использовать только первую или третью опцию

  Пример:

.data
 SQLString db "select telephoneNo from employee where name=?",0
 Sample1 db "Bob",0
 Sample2 db "Mary",0
.data?
 buffer db 21 dup(?)
 StrLen dd ?
.code
      ........
      invoke SQLPrepare, hStmt, addr SQLString,sizeof SQLString 
      invoke SQLBindParameter, hStmt, 1, SQL_PARAM_INPUT, SQL_C_CHAR, 
          SQL_CHAR, 20, 0, addr buffer, sizeof buffer, addr StrLen
 ;===========================================
 ; First run
 ;=========================================== 
      invoke lstrcpy, addr buffer, addr Sample1
      mov StrLen, sizeof Sample1
      invoke SQLExecute, hStmt
 ;===========================================
 ; Second run
 ;=========================================== 
      invoke lstrcpy, addr buffer, addr Sample2
      mov StrLen, sizeof Sample2

      invoke SQLExecute, hStmt

  Замечание! Мы связываем параметр с буфером только однажды и затем, мы изменяем содержание буфера и вызываем SQLEXECUTE несколько раз. Никакой потребности в вызыве SQLPREPARE не возникает, т.к. ODBC драйвер знает, где найти то, что требует параметр, потому что мы "сказали" ему об этом, вызыв SQLBindParameter.

  Мы пока игнорируем записи, возвращаемые запросом. Доступ и использование набора возвращаемых результатов - предмет будущих консультаций.

  Предположим, что вы выполнили некоторую инструкцию SQL и хотите выполнить новую инструкцию, вы не должны распределять новый операторный идентификатор . Вы должны просто развязать параметры (если необходимо) вызывая SQLFreeStmt с параметром SQL_UNBIND и SQL_RESET_PARAMS. Тогда вы сможете использовать операторный идентификатор для следующей инструкции SQL.

УДАЛЕНИЕ ИНСТРУКЦИИ

  Это делается вызывом SQLFreeHandle.

  [C] Iczelion, пер. SheSan

© 2002-2004 wasm.ru - all rights reserved and reversed