Студопедия

КАТЕГОРИИ:


Архитектура-(3434)Астрономия-(809)Биология-(7483)Биотехнологии-(1457)Военное дело-(14632)Высокие технологии-(1363)География-(913)Геология-(1438)Государство-(451)Демография-(1065)Дом-(47672)Журналистика и СМИ-(912)Изобретательство-(14524)Иностранные языки-(4268)Информатика-(17799)Искусство-(1338)История-(13644)Компьютеры-(11121)Косметика-(55)Кулинария-(373)Культура-(8427)Лингвистика-(374)Литература-(1642)Маркетинг-(23702)Математика-(16968)Машиностроение-(1700)Медицина-(12668)Менеджмент-(24684)Механика-(15423)Науковедение-(506)Образование-(11852)Охрана труда-(3308)Педагогика-(5571)Полиграфия-(1312)Политика-(7869)Право-(5454)Приборостроение-(1369)Программирование-(2801)Производство-(97182)Промышленность-(8706)Психология-(18388)Религия-(3217)Связь-(10668)Сельское хозяйство-(299)Социология-(6455)Спорт-(42831)Строительство-(4793)Торговля-(5050)Транспорт-(2929)Туризм-(1568)Физика-(3942)Философия-(17015)Финансы-(26596)Химия-(22929)Экология-(12095)Экономика-(9961)Электроника-(8441)Электротехника-(4623)Энергетика-(12629)Юриспруденция-(1492)Ядерная техника-(1748)

Создание приложений баз данных средствами ODBC

 

Различные СУБД представляют собственные API для взаимодействия с БД. Прикладные API включают наборы функций, обеспечивающие программиста разнообразными типами доступа к БД, такими как: подключение, выполнение операторов, выборка отдельных строк данных из результирующего множества запросов. Недостатком такого подхода является отсутствие универсальности – программа должна быть обработана предкомпилятором и связана с API, поставляемым в составе конкретной целевой СУБД.

Чтобы упорядочить данный подход, фирма Microsoft разработала стандарт, получивший название Open Database Connectivity – (ODBC). Технология ODBC предусматривает использование единого интерфейса для доступа к смешанным базам данных SQL, причем SQL рассматривается как базовое стандартное средство доступа к данным. Данный интерфейс (который встраивается непосредственно в язык С) обеспечивает высокую степень универсальности, в результате чего одно и тоже приложение может получать доступ к данным, хранящимся в базах различных целевых СУБД, без необходимости внесения изменений в его программный текст. Таким образом, разработчики получили инструмент, позволяющий создавать и распространять приложения архитектуры “клиент - сервер”, способные работать с широким спектром различных целевых СУБД. Для связи приложения с любой выбранной пользователем целевой СУБД достаточно лишь иметь соответствующий ODBC – драйвер.

Архитектура ODBC. Общая структура ODBC включает в себя следующие элементы: приложение, менеджер драйверов, драйверы баз данных, источники данных.(рис нарисовать)!.

Приложение выполняет обработку данных и вызов функций библиотеки ODBC для отправки SQL – операторов в СУБД и выборки возвращаемой СУБД информации.

Менеджер драйверов выполняет загрузку драйверов по требованию приложения. Представляет собой библиотеку DLL.

Драйверы баз данных обрабатывают вызовы функций ODBC и направляют SQL – запросы в конкретные источники данных, а также возвращают полученные результаты приложению. При необходимости драйверы выполняют модификацию исходного запроса приложения с целью привидения его в соответствие синтаксическим требованиям целевой СУБД. От них не требуется собственной реализации тех возможностей, которые данная СУБД не поддерживает. Единственным исключением из этого правила являются драйверы для СУБД, не имеющих собственных ядер. В этом случае ядро СУБД, обеспечивающее хотя бы минимальную поддержку языка SQL, должно быть реализовано в самом драйвере. В свете вышесказанного для драйверов ODBC можно говорить об их уровнях соответствия SQL. Различают драйверы с минимальным уровнем поддержки SQL, основным и расширенным уровнями поддержки.

Источники данныхсодержат те данные, доступ к которым необходим пользователю приложения. Данные сохраняются в базе данных, контролируемой целевой СУБД, операционной системой, а также сетевыми сервисами ОС.

Коды возврата. Все функции ODBC возвращают коды, чтобы показать в каком состоянии выполнения находится та или иная функция. Код возврата или RETCODE указывает на то, был ли вызов функции ошибочным или нет не указывает точной причины возникновения той или иной ошибки. В таблице приведены коды возврата ODBC и их краткие описания.

Таблица Коды возврата ODBC

Код возврата Описание
   
SQL_SUCCESS Функция выполнена успешно, информация об ошибке отсутствует
SQL_SUCCESS_WITH_INFO Функция выполнена успешно, однако есть некоторая предупреждающая информация
SQL_NO_DATA_FOUND Все строки результирующего множества извлечены. Это не является ошибкой, но указывает, что больше не осталось информации для выборки
SQL_ERROR Ошибка в процессе выполнения данной функции. Имеется дополнительная информация об ошибке для восстановления.
SQL_INVALID_HANDLE Возвращается функцией ODBC в случае, если какой-нибудь из идентификаторов-параметров данной функции является недействительным
SQL_STILL_EXECUTING Возвращается какой-либо асинхронно выполняющейся функцией, находящейся в процессе выполнения
SQL_NEED_DATA Возвращается функциями исполнения SQL – оператора в случае определения параметров операторов во время выполнения.

 

Проверка кодов возврата может выполняться посредством макросов RETCODE_IS_FAILURE или RETCODE_IS_SUCCESSFUL. Данные макросы приведены ниже:

 

#define RETCODE_IS_FAILURE (x) ((x) = = SQL_ERROR || \

(x) = = SQL_INVALID_HANDLE || \

(x) = = SQL_STILL_EXECUTING)

 

#define RETCODE_IS_SUCCESSFULL(x) (!RETCODE_IS_FAILURE(x))

 

Для использования макросов в программах ODBC, необходимо применять переменные типа кодов возврата, т.е. типа RETCODE, например:

 

#include <sql.h>

#include <windows.h>

RETCODE rc;

HENV henv;

rc =SQLAllocEnv(&henv);

if (RETCODE_IS_SUCCESSFULL(rc))

{операторы, выполняющиеся в случае истинности условия оператора if};

 

В приведенном примере переменная rc предназначена для определения кода возврата функции SQLAllocEnv().

Основной алгоритм программ ODBC. Основной алгоритм программ, использующих интерфейс ODBC, представлен на рисунке в виде блок-схемы алгоритма работы.

Как видно из рисунка любая программа с использованием ODBC может быть разделена на три основные части: инициализация, обработка оператора SQL и завершение программы. Главной частью программы ODBC является обработка оператора SQL, которая в свою очередь может быть разбита на собственные составные части. В ODBC, так же как и в динамическом PL/SQL при обработке произвольного SQL-оператора, необходимо выполнять связывание параметров. Собственно связывание выполняет драйвер ODBC, однако программа посредством API-функций должна корректно указать какие данные “связываются” и как в процессе связывание их трактовать. Если выполняемая инструкция это запрос на извлечение информации из базы данных, программа должна указать, куда считывать строки результирующего множества оператора и считать их.

 

Рисунок Основной алгоритм использования ODBC

в прикладных программах

 

Функции инициализации и завершения. Прежде чем прикладная программа сможет вызвать какую-либо из функций ODBC, она обязана выполнить инициализацию ODBC и установить окружение. ODBC использует окружение для отслеживания соединений с БД, установленного прикладной программой. В рамках одного окружения можно установить произвольное число соединений. Назначение окружения производится функцией ODBC SQLAllocEnv() и имеет следующий синтаксис:

 

RETCODE SQLAllocEnv (phenv)

Описание параметра phenv приведено в таблице.

Таблица Параметр SQLAllocEnv

Тип Аргумент Использование Описание
HENV* phenv Выход (аналог параметра out для PL/SQL ORACLE) Указатель области хранения в памяти идентификатора окружения

 

Освобождение идентификатора окружения происходит при вызове функции SQLFreeEnv(), который производится в программе последним. Описание функции имеет следующий вид:

 

RETCODE SQLFreeEnv(phenv)

 

Здесь параметр phenv имеет тот же смысл, что и в функции назначения окружения, однако в данном случае – это не “назначаемый”, а “освобождаемый” идентификатор и в отличие от SQLAllocEnv является входным (аналог in в PL/SQL).

Так же, как окружение прикладной программы представляется с помощью идентификатора окружения, идентификатор соединения представляет соединение между источником данных и прикладной программой. В отличие от окружения, идентификатор которого в программе один, идентификаторов соединения может назначаться несколько, для каждого источника данных, с которым прикладная программа предполагает соединиться. Назначение идентификаторов соединения производится посредством функции SQLAllocConnect(). Синтаксис следующий:

 

RETCODE SQLAllocConnect(henv, phdbc)

 

При вызове функция может возвращать: SQL_SUCCESS, SQL_SUCCESS_WITH_INFO, SQL_ERROR, SQL_INVALID_HANDLE. Параметры представлены в таблице:

 

Таблица Параметры SQLAllocConnect()

Тип Аргумент Использование Описание
HENV henv Вход Идентификатор окружения прикладной программы
HDBC* phdbc Выход Указатель области хранения памяти для идентификатора соединения

 

Менеджер драйверов распределяет память для соединения и возвращает идентификатор через phdbc. Парная для SQLAllocConnect() функция SQLFreeConnect() освобождает идентификатор доступа и возвращает все назначенные SQLAllocConnect() ресурсы (освобождает всю связанную с ним память):

 

RETCODE SQLFreeConnect(hdbc)

 

где параметр hdbc – входной параметр, представляющий освобождаемое соединение.

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

На базовом уровне API поддерживается лишь одна функция соединения, хотя на расширенных уровнях их достаточно много. Рассмотрим функцию SQLConnect() базового уровня.

SQLConnect() загружает драйвер и устанавливает соединение с источником данных. Идентификатор соединения ссылается на местоположение области хранения всей информации о соединении, включая его статус, состояние транзакции и информацию об ошибке. Синтаксис данной функции следующий:

 

RETCODE SQLConnect (hdbc, szDSN, sbDSN, szUID, sbUID, szAuthStr, cbAuthStr)

 

Таблица Параметры SQLConnect

Тип Аргумент Использование Описание
HDBC hdbc Вход Идентификатор соединения
UCHAR* szDSN Вход Имя источника данных
SWORD sbDSN Вход Длина szDSN. Может быть SQL_NTS в случае если строка имеет нулевое окончание.
UCHAR* szUID Вход Имя пользователя
SWORD sbUID Вход Длина szUID или SQL_NTS
UCHAR* szAuthStr Вход Строка авторизации
SWORD cbAuthStr Вход Длина строки авторизации или SQL_NTS

 

Значение SQL_NTS (null terminated string) удобно использовать в случае задания строковых литералов либо указателей на таковые в качестве имен источника данных, пользователя и пароля. В синтаксисе языка С строкой-константой с автоматически выставляемым нулевым окончанием является, как известно последовательность символов взятая в парные двойные кавычки. Если источник данных не требует имени пользователя, то в функцию должны быть переданы либо нулевое значение, либо пустая строка (строка, состоящая лишь из нуль-терминатора), в качестве же размера указывается либо нулевое значение, либо SQL_NTS соответственно. То же самое касается и строки авторизации.

Так для того, чтобы установить соединение с источником данных, требующим имя пользователя и пароль, вызов SQLConnect() может быть следующим:

 

RETCODE rc;

//…промежуточные операторы

rc =SQLConnect (hdbc, “RESTAURANTS”, SQL_NTS, “OWNER”,

SQL_NTS, “ICE-CREAM”, SQL_NTS).

 

Разрыв соединения с источником данных выполняет вызов SQLDisconnect():

 

RETCODE SQLDisconnect (hdbc)

 

где hdbc – входной параметр функции, представляющий идентификатор доступа для отсоединения.

Выполнение операторов. В данном разделе рассмотрим два набора функций: функции управления каталогом и выполнения SQL – операторов. Функции управления каталогом возвращают информацию из системного каталога источника данных: имена таблиц, столбцов, табличную статистику и т. д. Функции выполнения операторов включают в себя функции непосредственного и подготовленного выполнения и связывания параметров.

Любая функция, которая имеет отношение к обработке или передаче SQL – оператора, требует в качестве параметра идентификатор оператора. Идентификатор оператора аналогичен идентификатору окружения или соединения за исключением того, что он ссылается на SQL – оператор. Идентификатор соединения может быть связан с несколькими идентификаторами операторов, но каждый идентификатор оператора связан только со своим идентификатором соединения. Назначение идентификатора оператора производится вызовом SQLAllocStmt(), которая выделяет область хранения в памяти для идентификатора оператора и связывает его с соединением, которое определяется собственным идентификатором.

Синтаксис для SQLAllocStmt() имеет вид:

 

RETCODE SQLAllocStmt(hdbc, phstmt)

 

Таблица Описание параметров SQLAllocStmt()

Тип Аргумент Использование Описание
HDBC hdbc Вход Идентификатор соединения
HSTMT* phstmt Выход Указатель области хранения в памяти для идентификатора оператора

 

Парная для SQLAllocStmt() функция SQLFreeStmt() выполняет следующие действия:

- останавливает любые SQL – операторы, которые в данный момент обрабатываются и связаны с заданным идентификатором оператора,

- закрывают любые открытые курсоры, которые имеют отношение к определенному идентификатору оператора,

- отбрасывает ожидаемые результаты,

- дополнительно, освобождает все ресурсы, связанные с определенным идентификатором оператора.

Синтаксис SQLFreeStmt() имеет следующий вид:

 

RETCODE SQLFreeStmt (hstmt, fOption)

 

Таблица Функция SQLFreeStmt

Тип Аргумент Использование Описание
HSTMT hstmt Вход Идентификатор оператора
UWORD fOption Вход Одна из следующих опций: SQL_CLOSE, SQL_DROP SQL_UNBIND SQL_RESET_PARAMS

 

Опция SQL_CLOSE отбрасывает неизвлечённые результаты и закрывает любые связанные с ними курсоры. Эта опция не влияет на соответствующие параметры, подготовленные операторы или соответствующие столбцы результата.

SQL_DROP освобождает все ресурсы, связанные с идентификатором, закрывает курсор, если он открыт и отбрасывает все ожидаемые строки результирующего множества. Эта опция завершает все обращения к hstmt, так как после успешного вызова SQLFreeStmt с этим параметром, идентификатор становится недействительным.

SQL_UNBIND освобождает (“отвязывает”) все буферы столбцов, связанные со столбцами результирующего множества запроса посредством SQLBindCol(). Описание данной функции приведено в разделе 2.5 данного методического пособия.

SQL_RESET_PARAMS освобождает все буферы параметров с фактическими значениями, связанные с маркерами параметров строки запроса. Связывание формальных параметров запроса (маркеров) с буферами фактических значений производится функцией SQLBindParametr(), описание которой приводится ниже в данном разделе.

Функции управления каталогом. Первая информация, которая может понадобиться прикладной программе для соединения с неизвестным источником данных – это информация о таблицах. ODBC-функция SQLTables возвращает список имен таблиц, которые содержит указанный источник данных. Используя идентификатор оператора, драйвер возвращает информацию в виде результирующего множества. Синтаксис SQLTables имеет вид:

 

RETCODE SQLTables (hstmt, szTableQualifier, sbTableQualifier,

szTableOwner, sbTableOwner, szTableName,

sbTableName, szTableType, sbTableType)

 

Таблица Описание параметров SQLTables

Тип Аргумент Использование Описание
HSTMT hstmt Вход Идентификатор оператора
UCHAR* szTableQualifier Вход Имя квалификатора или “”, означающая, что таблицы не имеют квалификаторов
SWORD sbTableQualifier Вход Длина szTableQualifier или SQL_NTS
UCHAR* szTableOwner Вход Образец строки поиска для имен собственников или “”, означающая что данная база не поддерживает имен собственников.
SWORD sbTableOwner Вход Длина szTableOwner или SQL_NTS
UCHAR* szTableName Вход Образец строки поиска для имен таблиц.
SWORD sbTableName Вход Длина szTableName или SQL_NTS
UCHAR* szTableType Вход Список типов таблиц для выбора.
SWORD sbTableType Вход Длина szTableType или SQL_NTS

 

В образцах строк для поиска возможно использование символов-заменителей, так ‘%’ заменяет любую последовательность символов, а ‘-‘ – произвольный одиночный символ. Список типов таблиц для выбора может содержать следующие типы таблиц: ‘TABLE’,’VIEW’, ‘SYSTEM TABLE’, ‘ALIAS’ и некоторые таблицы. Представления (‘VIEW’) вообще-то не являются таблицами БД, но зачастую носят имя “виртуальных таблиц” в силу похожести использования для операторов извлечения. Если символ ‘%’ используется в каком-то из аргументов функции в качестве шаблона выбора, а все остальные аргументы шаблонов – пустые строки, то можно получить список всех квалификаторов, владельцев или таблиц для выбранного источника. При использовании такого способа вызова все столбцы в результирующем множестве, кроме одного, устанавливаются в NULL.

Например, следующий вызов возвратит список всех таблиц и представлений:

 

rc=SQLTables (hstmt, “”, SQL_NTS, “”,SQL_NTS, “%”, SQL_NTS, “’TABLE’, ‘VIEW’”, SQL_NTS).

 

Результирующее множество функции SQLTables одно и тоже для любого её вызова и представлено в таблице.

Таблица Результирующее множество SQLTables

Имя столбца Тип данных Объяснение
TABLE_QUALIFIER VARCHAR(128) Идентификатор квалификатора
TABLE_OWNER VARCHAR(128) Идентификатор собственника
TABLE_NAME VARCHAR(128) Идентификатор таблицы
TABLE_TYPE VARCHAR(128) Идентификатор типа таблицы (“TABLE”, “VIEW” и др. строки)
REMARKS VARCHAR(256) Описание таблицы

 

Как только информация о таблицах получена, зачастую бывает необходимо получить информацию о столбцах интересующей таблицы. Чтобы выбрать эту информацию, программа должна вызвать SQLColumns(). При вызове драйвер, используя идентификатор оператора, возвращает эту информацию в результирующем множестве:

Таблица Результирующее множество SQLColumns()

Имя столбца Тип данных Описание
TABLE_QUALIFIER VARCHAR(128) Идентификатор квалификатора
TABLE_OWNER VARCHAR(128) Идентификатор собственника
TABLE_NAME VARCHAR(128) Название таблицы
COLUMN_NAME VARCHAR(128) Название столбца
DATA_TYPE Smallint SQL – тип данных
TYPE_NAME VARCHAR(128) Имя типа данных в зависимости от источника
PRECISION Integer Точность
LENGTH Integer Длина столбца
SCALE Smallint Масштаб
NULLABLE Smallint SQL_NO_NULLS SQL_NULLABLE SQL_NULLABLE_UNKNOWN
REMARKS VARCHAR(254) Описание таблицы

 

Столбцы DATA_TYPE и TYPE_NAME определяют тип данных по разному. DATA_TYPE является ODBC SQL – типом данных, а TYPE_NAME является специфическим типом данных источника. Один и тот же ODBC SQL –тип может иметь разные типы данных для каждого источника. Столбцы PRECISION и SCALE можно использовать в других функциях (например в функции SQLBindParameter). PRECISION определяет общее число цифр или максимальную длину, а SCALE определяет количество цифр справа от десятичной точки и используется для числовых столбцов.

Синтаксис же функции следующий:

 

RETCODE SQLColumns (hstmt, szTableQualifier, sbTableQualifier,

szTableOwner, sbTableOwner, szTableName,

sbTableName, szColumnName,

sbColumnName)

 

Таблица Описание параметров SQLColumns

Тип Аргумент Использование Описание
HSTMT hstmt Вход Идентификатор оператора
UCHAR* szTableQualifier Вход Квалификатор таблиц, “” означает, сто таблицы источника не поддерживают квалификаторов
SWORD sbTableQualifier Вход Длина szTableQualifier
UCHAR* szTableOwner Вход Образец строки поиска для имен собственников
SWORD sbTableOwner Вход Длина szTableOwner
UCHAR* szTableName Вход Образец строки поиска для имен таблиц
SWORD sbTableName Вход Длина szTableName
UCHAR* szColumnName Вход Образец строки поиска для имен столбцов
SWORD sbColumnName Вход Длина szColumnName

 

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

Непосредственное выполнение. Непосредственное выполнение целесообразно использовать в следующих случаях:

- SQL – операторы, которые должны быть выполнены, выполняются только один раз;

- не требуется информация о результирующем множестве до выполнения оператора.

Непосредственное выполнение реализуется с помощью функции SQLExecDirect() и представляет наиболее быстрый способ запуска SQL – оператора при одноразовом выполнении.

Синтаксис функции имеет вид:

 

RETCODE SQLExecDirect(hstmt, szSqlStr, sbSqlStr)

Таблица Описание параметров 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 – операторе.

 

RETCODE SQLBindParameter(hstmt, ipar, fParamType, fCType, fSqlType,

cbColDef, ibScale, rgbValue, cbValueMax,

pcbValue)

 

Таблица Параметры функции 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.
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() приведено в таблице 30. Как и любая функция ODBC эта функция возвращает данные типа RETCODE.

 

Таблица Описание параметров SQLParamData()

Тип Аргумент Использование Описание
HSTMT hstmt Вход Идентификатор оператора
PTR prgbValue Выход Указатель области хранения в памяти значения, которое было определено для аргумента rgbValue (идентификатор параметра требующего данные) в SQLBindParameter() (для значений параметров) или адрес буфера rgbValue, определенный в SQLBindCol() (для значений выбираемых столбцов результирующего множества).

 

Как только параметр, определяемый во время выполнения, будет связан, прикладная программа может выполнить SQL – оператор. Кодом возврата функции выполнения (SQLExecute() или SQLExecDirect()) будет SQL_NEED_DATA. Затем прикладная программа предоставляет необходимые данные с помощью функции SQLParamData() и SQLPutData().

Функция SQLPutData() позволяет передавать данные в качестве значений параметров во время выполнения оператора. Функция использует следующие аргументы:

Таблица Описание параметров 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(). Данная функция продвигает курсор вперед на одну строку до тех пор, пока он не будет установлен за последней строкой результирующего множества.

 

ВЫБОРКА ИНФОРМАЦИИ О РЕЗУЛЬТИРУЮЩЕМ МНОЖЕСТВЕ. Прежде чем выбрать данные из результирующего множества прикладной программе может понадобиться некоторая информация о нём.

В ODBC существует несколько таких функций, в данном же пособии рассматриваются только две из них.

Для определения числа столбцов, которые были возвращены с помощью подготовленного или выполненного оператора, прикладная программа выполняет функцию SQLNumResultCols(), которая имеет следующий синтаксис:

 

RETCODE SQLNumResultCols (hstmt, pccol)

 

Таблица Параметры SQLNumResultCols

Тип Аргумент Использование Описание
HSTMT hstmt Вход Идентификатор оператора
SWORD* pccol Выход Число столбцов в результирующем множестве

Для возвращения числа строк, на которые воздействовал SQL – оператор, прикладная программа вызывает функцию SQLRowCount(). Данная функция возвращает число строк на которые воздействовал оператор update, insert или delete и имеет следующий синтаксис:

 

RETCODE SQLRowCount (hstmt, pcrow)

 

Таблица Параметры SQLRowCount()

Тип Аргумент Использование Описание
HSTMT hstmt Вход Идентификатор оператора
SDWORD* pcrow Выход Для операторов update, insert или delete определяет число строк на которые воздействовал оператор, или -1, если число таких строк не определяется. Для других операций драйвер может определить pcrow. Например, некоторые источники данных могут возвращать число строк, которые были возвращены оператором select или функцией каталога до извлечения этих строк. Однако много источников не могут возвращать число строк в результирующем множестве до их извлечения. Следовательно, прикладная программа не должна полагаться на результаты, возвращаемые в SQLRowCount().

БАЗОВЫЕ ФУНКЦИИ ВЫБОРКИ ДАННЫХ. Как только закончена выборка информации о результирующем множестве, можно приступать к выборке собственно результирующего множества. В ODBC существует две функции базового уровня для выборки результатов: SQLBindCol() и SQLFetch(). Функция SQLBindCol() определяет область хранения данных результирующего множества, а SQLFetch() осуществляет выборку данных в области хранения. Алгоритм программы, использующей эти функции для возвращения данных из всех строк результирующего множества, предполагает выполнение следующих шагов:

1. Вызов SQLBindCol() один раз для каждого столбца, который должен быть возвращен из результирующего множества,

2. Вызов SQLFetch() для перемещения курсора на следующую строку и возврата данных из связанных столбцов,

3. Повторение шага 2 до тех пор пока SQLFetch() не возвратит SQL_NO_DATA_FOUND. Это указывает на то, что был достигнут конец результирующего множества. Если результирующее множество является пустым, то SQL_NO_DATA_FOUND будет возвращен сразу же при первом вызове SQLFetch().

Функция SQLFetch() извлекает строку данных из результирующего множества для выполненного SQL – оператора. Драйвер возвращает данные для всех столбцов, которые были связаны для предварительного хранения данных с помощью функции SQLBindCol(). Синтаксис функции SQLFetch():

 

RETCODE SQLFetch (hstmt)

Здесь HSTMT – идентификатор выполненного оператора.

 

Если необходимо определить область хранения данных результирующего множества, которые должны быть извлечены, то вызывается функция SQLBindCol(). Каждый столбец, который требуется выбрать, связывается с помощью отдельного вызова функции.

Функция SQLBindCol() назначает область хранения в памяти и тип данных для столбца результирующего множества. Она определяет:

- буфер хранения для получения содержимого столбца данных в результирующем множестве;

- длину указанного буфера хранения;

- область памяти для хранения длины столбца выборки;

- преобразование типа данных.

Синтаксис данной функции имеет следующий вид:

 

RETCODE SQLBindCol (hstmt, icol, fcType, rgbValue, cbValueMax, pcbValue)

 

Таблица Параметры функции SQLBindCol()

Тип Аргумент Использование Описание
       
HSTMT hstmt Вход Идентификатор оператора
UWORD icol Вход Номер столбца результирующего множества, упорядоченный слева направо, начиная с 1
SWORD fcType Вход С – тип данных столбца результирующего множества. Некоторые из возможных значений: SQL_C_BINARY, SQL_C_BIT, SQL_C_CHAR, SQL_C_DEFAULT, SQL_C_FLOAT, SQL_C_SLONG, SQL_C_SSHORT, SQL_C_ULONG, SQL_C_USHORT. SQL_C_DEFAULT определяет, что данные должны быть переданы в С – тип по умолчанию.
PTR rgbValue Вход Указатель области хранения данных. Если является нулевым указателем, то драйвер “отвязывает” столбец. Для “отвязывания” всех столбцов программа вызывает SQLFreeStmt() с опцией SQL_UNBIND.
SDWORD cbValueMax Вход Максимальная длина буфера rgbValue. Для символьных данных буфер должен предусматривать место для нуль – окончания строки.
SDWORD* pcbValue Вход SQL_NULL_DATA или размер возвращаемой в rgbValue строки. Если размер строки не может быть определен, то по адресу pcbValue размещается SQL_NO_TOTAL.
SDWORD* pcbValue Вход Если размер строки не может быть определен, или больше cbValueMax, то данные в rgbValue усекаются до размера, определенного в cbValueMax и имеют нулевое окончание, благодаря драйверу. Для двоичных данных выполняется то же самое с поправкой на нуль – окончание. Для всех других типов данных значение cbValueMax игнорируется и драйвер считает, что размер rgbValue равен размеру С – типа данных, определенного в fcType.

 

Приведем пример программы, использующей средства ODBC:

 

#include <sql.h>

#include <stdio.h>

#include <stdlib.h>

#define MAX_STMT_LEN 100

main()

{

HENV henv; /*идентификатор среды*/

HDBC hdbc; /*идентификатор соединения*/

HSTMT hstmt; /*идентификатор оператора*/

RETCODE rc; /*код возврата*/

UCHAR selstmt [MAX_STMT_LEN] /*строка оператора*/

UCHAR address [30];

UCHAR tel_no [15];

UCHAR pos [25];

SDWORD address_len, tel_no_len, pos_len;

SQLAllocEnv (&henv);

SQLAllocConnect (henv, &hdbc);

 

rc=SQLConnect (hdbc, “drhome”, SQL_NTS, “student”, SQL_NTS, “student”,

SQL_NTS);

if (rc = = SQL_SUCCESS || rc = = SQL_SUCCESS_WITH_INFO)

{

SQLAllocStmt (hdbc,&hstmt);

lstrcpy (selstmt, “ select address, tel_no, position from staff

where lname = ‘Иванов’ and fname = ‘Иван’ ”);

if (SQLExecDirect (hstmt, selstmt, SQL_NTS)!= SQL_SUCCESS)

exit (-1);

SQLBindCol (hstmt, 1, SQL_C_CHAR, address,

(SDWORD)sizeof(address), address_len);

SQLBindCol (hstmt, 2, SQL_C_CHAR, tel_no,

(SDWORD)sizeof(tel_no), tel_no_len);

SQLBindCol (hstmt, 3, SQL_C_CHAR, pos,

(SDWORD)sizeof(pos), pos_len);

 

while(RETCODE_IS_SUCCESSFULL(rc))

{

rc=SQLFetch (hstmt);

if (RETCODE_IS_SUCCESSFULL(rc))

{

/*…вывод возвращенных строк…*/

}

}

SQLFreeStmt (hstmt, SQL_DROP);

SQLDisconnect (hdbc);

}

SQLFreeConnect (hdbc);

SQLFreeEnv(henv);

}

 

П одробный алгоритм использования ODBC в прикладных программах. О бобщенную блок-схему алгоритма использования ODBC в прикладных программах (рисунок) операторов SQL можно представить в виде, изображенном на рисунке.

 

Рисунок Блок схема обработки SQL-операторов в ODBC

 

Литература

1. Коннолли, Т. Базы данных: проектирование, реализация и сопровождение. Теория и практика / Т. Коннолли, К. Бегг. - 3 изд., перераб. - M.: Вильямс, 2003 -1440 с.

2. Кайт, Том. Oracle для профессионалов. В 2-х томах / Том Кайт; пер. с англ. – СПб.1: ООО «ДиаСофтЮП», 2005. – Ч. 1 – 672 с.; – Ч. 2 – 816 с.

3. Скотт, Урман. Oracle 8.i Новые возможности программирования на языке PL/SQL / Урман Скотт. - M.: Лори, 2001. - 680 с.

4. Скотт, Урман. Oracle Database 10g. Программирование на языке PL/SQL. / Урман Скотт, Рон Хардман, Майкл МакЛафлин. - M.: Лори, 2007. - 816 с.

5. Гринвальд,Рик. Oracle. Справочник. Пер. с англ. / Рик Гринвальд, Дэвид К. Крейнс – СПб: Символ-Плюс, 2005. – 976 с.

6. Кайт, Том. Oracle для профессионалов: архитектура, методики программирования и основные особенности версий 9i и 10g / Том Кайт; пер. с англ. – М.: Лори, 2008. – 848 с.

7. Кайт, Том. Эффективное проектирование приложений / Том Кайт; пер. с англ. – М.: Издательство "Лори", 2006. – 656 с.

8. Бобровски, С. Oracle 8.i Архитектура / С. Бобровски. - М.: Лори, 2001. - 224с.

 

 

<== предыдущая лекция | следующая лекция ==>
Встроенный динамический SQL | Основные сведения о СУБД Oracle
Поделиться с друзьями:


Дата добавления: 2014-01-04; Просмотров: 901; Нарушение авторских прав?; Мы поможем в написании вашей работы!


Нам важно ваше мнение! Был ли полезен опубликованный материал? Да | Нет



studopedia.su - Студопедия (2013 - 2024) год. Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав! Последнее добавление




Генерация страницы за: 0.282 сек.