WWW.DISSERS.RU

БЕСПЛАТНАЯ ЭЛЕКТРОННАЯ БИБЛИОТЕКА

   Добро пожаловать!

Pages:     | 1 |   ...   | 2 | 3 || 5 | 6 |

«Вячеславович Фролов, Григорий Вячеславович Фролов в Интернете практическое руководство по созданию Web-приложений с базами данных Издание исправленное УДК 004.7 ББК 32.973.202 Фролов А. В., Фролов Г. ...»

-- [ Страница 4 ] --

= Таблица 5-4. Значения свойства DBPROP_INIT_PROMPT Значение с: помощью которой пользователь должен ввести информацию, необходимую для источника данных Выводит указанную только в том случае, если требуется внести параметры инициали зации Аналогично предыдущему, но пользователю не ется вводить информацию Панель приглашения Что же касается собственно имени источника то оно записывается в ноле как строка типа = VT_BSTR;

Аналогичным образом заполняются элементы массива за имя и его пароль:

= = VT_BSTR;

= задающее имя пользователя, имеет идентификатор USERID, а определяющее пользователя, — идентификатор Здесь для простоты мы опустили инициализацию и Она выполняется аналогично тому, как это делается для массива, определяющих уровень и имя источника данных.

На данном этапе мы подготовили массив структур DBPROP, содержащий параметры для установки свойств объекта источника данных. Те перь нужно задать свойства.

Установка свойств свойств выполняется методом SetProperties интерфейса Этому методу передается указатель па структуру DBPROPSET, который, в свою очередь, для ссылки только что подготовленный нами массив структур DBPRQP.

Структура DBPROPSET определена следующим образом:

Глава 5. приложений с базами данных через OLE DB struct tagDBPROPSET * rgProperties;

} Ее описаны в таблице 5-5.

Таблица 5-5. Поля структуры DBPROPSET Поле Описание на массив структур DBPROP. Содержимое поля иг норируется, если в поле cProperties находится нулевое значение cProperties свойств, для которых выполняется или чтения массива структур DBPROP) guidPropertySet Глобальный уникальный идентификатор набора свойств Структура DBPROPSET создается и инициализируется очень просто:

DBPROPSET DBPROPSET_DBINIT;

= 4;

= В поле guidPropertySet мы константу так как наш набор отвечает за источника Массив rglnit Properties состоит из элементов, поэтому в поле cProperties записы вается значение 4. Что касается указателя на массив, то мы его rgProperties.

Теперь у нас есть структура, описывающая массив Чтобы свойства, нам метод SetProperties ties. А для этого, в свою очередь, нам потребуется указатель на интерфейс Необходимый указатель мы получаем с помощью функции и записываем в переменную pIDBProperties типа pIDBProperties;

Через первый параметр мы Queryl nterface глобальный уникальный идентификатор В нашем случае идентификатором интерфейса IDBProperties служит значение константы IID_IDBProperties.

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

Теперь мы можем устанавливать HRESULT = Метод SetProperties интерфейса IDBProperties имеет два параметра. Через второй параметр передается указатель на массив структур типа DBPROPSET, а че рез первый — количество таких структур в массиве. В нашем случае подготов данных в Интернете.

лена одна структура описывающая массив DBPROP, поэтому значение первого параметра равно 1.

Для показали на рис. 5-1 взаимосвязь структур и DBPROP при установке свойств источника DBPROPSET ID Рис. Задание свойств источника данных Здесь мы подготовили массив из трех структур DBPROPSET, поэтому первый параметр метода SetProperties интерфейса имеет значение, рав ное 3.

После того как программа свойства методом SetProperties, ин терфейс IDBProperties станет нам не Поэтому мы освобождаем указатель на интерфейс методом Release:

Инициализация Последний этап в инициализации провайдера источника данных — вы зов метода Initialize интерфейса IDBInitialize:

что указатель па интерфейс мы получили на этапе создания объекта источника данных функцией = NULL, В том случае, если значения свойств указаны правильно, инициализация пройдет успешно. Теперь переходить к созданию сеанса и выдаче Для этого нам опять потребуется интерфейс IDBInitialize.

Глава 5. Связь приложений с данных через OLE DB Объект Session Прежде чем команды, нам необходимо создать сеанс как объект Ses sion. Этот объект обеспечивает для создания команд, наборов записей, для создания и изменения таблиц и индексов. Он также применяется для пост объектов в этой книге мы этот случай не рассматри ваем.

Для создания объекта Session нужно получить указатель на интерфейс IDBCreateSessi on. Для этого метод интерфейса вызвав его образом:

IDBCreateSession* В качестве первого параметра мы передаем методу Querylnterface идентифи катор интерфейса IDBCreateSession в виде константы IID_IDBCreateSession. В случае успеха метол указатель на IDBCreateSession в переменную, расположенную по адресу, заданному вторым параметром. В случае указатель на интерфейс будет храниться в переменной pIDBCreateSession типа IDBCreateSession*.

С помощью интерфейса IDBCreateSession и метода CreateSession мы созда ем сеанс:

hr = Если новый сеанс создается в рамках объекта, через первый параметр методу CreateSession передается указатель на управляющий интерфейс Если же сеанс не является составной частью агрегированного объекта (как в нашем случае), Вы указать здесь значение NULL.

Второй параметр метода CreateSession предназначен для передачи иденти фикатора интерфейса. При создании сеанса мы получаем интерфейс, средства ми которого можно создавать команды. Идентификатор этого зада ется константой И наконец, через третий параметр методу CreateSession передается адрес в которой будет указатель на интерфейс создания команд.

После получения интерфейса создания команд IDBCreateCommand мы дим ненужный нам более указатель на интерфейс IDBCreateSession с помощью метода Release:

Объект Command Объект Command необходим для выдачи команд. Он создается при помощи да IDBCreateCommand.

Создание Ниже показан фрагмент кода, создающего объект Command:

242 Базы данных Интернете. Практическое руководство ICommandText* hr Рассмотрим параметры использованного метода параметр предназначен для передачи управляющего интерфейса lUnknown при агрегации. Мы не применяем агрегацию, поэтому указываем здесь NULL.

Через второй параметр передается идентификатор интерфейса ICommandText, необходимого для определения Третий параметр передает указатель па переменную, в которую будет запи сан указатель на только что упомянутый интерфейс ICommandText.

После успешного получения указатель на интерфейс ICommandText мы можем освободить указатель на интерфейс который больше не потребуется:

Эта операция выполняется как обычно, при помощи метода Release.

Определение команды Для определения команды мы используем метод SetCommandText ICommandText:

LPCTSTR = ClientID, Password, RegisterDate, Email FROM wSQLString);

Первый параметр метода SetCommandText синтаксис команды и общие правила, которые провайдер источника данных в процессе разбора строки Текст команды задается вторым параметром.

Если первый параметр метода задан в виде константы DBGUIO_SQL (как в нашем то команда в соответствии с правилами языка SQL.

В том случае, когда этот параметр как DBGUID_DEFAULT, способом, заданным для провайдера источника данных по умолча нию. В частности, провайдер OLE DB может по умолчанию выполнять коман ды, не имеющие к SQL.

Выполнение команды После определения команды можно отправить ее на выполнение при помощи метода Execute интерфейса ICommandText:

LONG = NULL, Первый параметр Execute используется для агрегирования. Мы зада ем его в виде константы NULL.

Второй параметр задает интерфейса необходимого для извлечения результата работы команды в виде набора записей. Метод Execute записывает указатель на интерфейс IRowset в переменную, адрес кото рой определен в последнем параметре.

Глава 5. приложений с базами данных через OLE DB Третий на структуру DBPARAMS, для запуска команд с параметрами. В этой книге мы не будем рассматривать такие команды. Если Вы можете здесь значение NULL.

Через четвертый параметр методу Execute указатель на ную, куда после команды записывается счетчик строк, на которые Например, при создании набора записей в нения команды SELECT в эту будет записано количество строк в наборе записей.

После выполнения команды мы должны освободить указатель на интерфейс вызвав метод Release:

Интерфейс IRowset и набор записей Как мы только что в результате выполнения методом Execute мы получаем указатель на интерфейс IRowset. Этот интерфейс для извлечения результатов выполнения команды, то есть для извлечения данных из полей строк набора записей, созданного командой.

Помимо этого интерфейса, нам потребуются и Для извлечения данных из записей нам предстоит выполнить следу ющие 4 получить описание столбов набора записей при помощи метода интерфейса выполнить привязку данных набора к переменным программы с помощью метода CreateAccessor интерфейса lAccessor;

идентификаторы строк набора методом интерфейса IRowset;

из полей строк методом GetData интерфейса IRowset.

Рассмотрим этих Получение набора записей На первом обработки набора записей нам нужно получить описание стол бцов вызвав метод Get Col umnl nf o IColumnsInfo.

Для этого мы вначале получим указатель на интерфейс восполь зовавшись для этого указателем на который стал доступным после команды:

Указатель на интерфейс IColumnsInfo извлекается с помощью метода Query Interface. первый параметр мы передаем этому методу идентификатор ICol umnsInf o в виде константы IID_ICol umnsInfo, а через второй параметр — указатель на переменную, в которую будет записан указатель на интерфейс Далее мы вызовем метод GetCol umnl nfo интерфейса IColumnsInfo:

244 Базы данных в Интернете. Практическое ULONG DBCOLUMNINFO* pColInfo = NULL;

= NULL;

hr = Методу через параметры передаются три указателя на перемен ные, в которые будет записана информация о столбцах набора записей.

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

Через второй параметр методу GetCol umnl nf o передается адрес в которую будет записан адрес массива структур DBCOLUMNINFO, описывающих столбцы набора.

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

Структура DBCOLUMNINFO определена так:

struct { LPOLESTR pwszName;

* ULONG DBCOLUMNFLAGS ULONG DBTYPE BYTE bPrecision;

BYTE bScale;

} DBCOLUMNINFO;

Поля этой структуры описаны в 5-6.

Таблица 5-6. Поля структуры DBCOLUMNINFO Поле Описание pwszName Указатель на имя или NULL, если имя столбца определить не удалось pTypelnfo Зарезервировано iOrdinal номер столбца. с 1, причем стол бец закладки типа bookmark имеет нулевой помер характеристик столбца. Набор флагов определен в рамках речисления DBCOLUMNFLAGS Максимальная длина значения в столбце wType данных, в столбце bPrecision Максимальная точность численных данных или длина строки, в кото рой представлены данные других Глава 5. Связь приложений с базами данных через OLE OB Таблица 5-6. Поля структуры (продолжение) Поле Описание bScale Количество цифр справа от точки для данных типа или DBTYPE_NUMERIC Идентификатор После получения информации о столбцах набора мы должны освободить ненужный в работе на интерфейс о:

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

Поле dwFlags может содержать константы, объединенные логической опера (таблица 5-7).

Таблица 5-7. Константы для заполнения Константа Описание Отсроченное чтение с кэшированием Столбец содержит закладку bookmark Столбец содержит (chapter D8COLUMNFLAGS_ISFIXEDLENGTH Все данные в столбце имеют одну и ту же длину Столбец содержит данные типа BLOB Этот флажок в том случае, если столбец может содержать значения NULL или если ис точника данных способен определить, может ли зна чение полей столбца быть равно NULL Столбец сохраняемой строки содержит отметку о времени или другое значение, используемое для версий записей, которое обновлять при помощи опера ций прямой могут содержать значения NULL DBCOLUHNFLAGS_MAYDEFER Отложенный столбец. Данные такого столбца не извле каются источника данных до тех пор, пока потреби тель данных не их извлечь Для данного столбца можно вызывать метод SetData DBCOLUMNFLAGS WRITE предназначенного для изме записи. Если этот флажок не записи данного столбца доступны только для чтения.

Этот флажок не используется совместно с Данные в как метода SetData интерфейса IrowsetChange, так и с применением других механизмов.

Этот флажок используется совместно с DBCOLUMNFLAGS WRITE Базы данных в Интернете. Практическое руководство Что же касается типа данных, указанного в поле то в таблице 5-8 мы перечислили некоторые значения для провайдера сервера Microsoft SQL Server.

Таблица 5-8. Типы данных Тип в Microsoft Тип данных OLE SQL Server Описание DBTYPE STR char Строка символов ANSI, закрытая varchar двоичным нулем text DBTYPE BYTES binary timestamp image numeric Численное значение, имеющее decimal точность и масштаб.

Описывается структурой struct { BYTE precision;

BYTE scale;

BYTE BYTE } Здесь precision количество десятичных цифр, scale — количество цифр от десятичной sign — знак (1 дли чи сел и 0 для отрицательных), — чис ло, занимающее в памяти 16 байт tinyint Целое без знака, занимающее в памяти 1 байт smallint Двухбайтовое целое со знаком int Целое со в байта real с плавающей десятичной точ кой одинарной точности float Аналогично по двойной точ ости DBTYPE DATE Значение типа double. Целая часть этого содержит количество дней.

с 30 декабря 1899 года, а дробная — прошедшую часть текущего дня Глава 5. Связь приложений с базами данных через OLE Таблица 5-8. Типы данных (продолжение) Тип в Microsoft Тип данных OLE DB SQL Server Описание DBTYPE Структура типа DBTIMESTAMP:

struct SHORT month;

day;

USHORT hour;

USHORT minute;

USHORT second;

fraction;

} Поля этой структуры хранят значения месяца, дня, количество часов, минут и а дробную часть DBTYPE CY типа Это число money с фиксированной десятичной причем от точки указаны цифры. Хранится как знаковое занимающее в памяти 8 байт, с масшта бом 10 Тип Тип данных может иметь переменную длину Продолжим извлечения значений из полей набора записей, образо ванного в результате На данный момент мы извлекли характеристики столбцов набора данных и готовы привязку данных.

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

Массив создается образом:

= NULL;

pDBBind = new Размер массива равен количеству строк в полученном наборе записей, кото рое мы определили на предыдущем этапе при помощи метода интерфейса Определение структуры DBBINDING показано ниже:

typedef struct tagDBBINDING :

ULONG ULONG ULONG (см. стр.) Базы данных в Интернете. Практическое руководство * * pObject;

DBBINDEXT * pBindExt;

DBPART dwPart;

LONG DWORD DBTYPE BYTE bPrecision;

BYTE DBBINDING;

Как видите, некоторые поля этой структуры называются также как и поля структуры Они имеют аналогичное назначение. Полное описание полей данной структуры Вы найдете в таблице 5-9.

Таблица 5-9. Поля структуры DBBINDING Поле Описание Порядковый номер столбца. Нумерация начинается с при чем столбец закладки типа bookmark имеет нулевой номер Смещение значения в буфере потребителя данных. Если буфер дан ных содержит строку записей, это смещение должно указывать на поле строки, соответствующее столбцу, заданному в поле iOrdinal.

Применяется только в том случае, если в поле dwPart установлен фла жок VALUE Смещение значения размера поля в буфере потребителя данных.

только в том случае, если поле dwPart установлен флажок DBPART_LENGTH obStatus Смешение значения слова состояния поля в буфере потребителя дан ных.

Используется только в том случае, если в поле установлен флажок pTypelnfo Зарезервировано pObject Указатель на типа DBOBJECT. Применяется при работе с по лями типа BLOB или с полями, содержащими объекты СОМ. В нашей книге не Указатель на структуру DBBINDEXT, которую можно использовать для дальнейших расширений структуры привязки данных dwPart Набор флагов, логической операцией ИЛИ и определя ющих, какая область буфера пользователя привязана к столбцам или Может принимать значения DBPART_VALUE, и DBPART_STATUS Способ получения памяти для хранения данных. Может принимать значения и В пер вом случае за работу с памятью отвечает потребителя данных, а во втором — источника данных Глава 5. Связь приложений с базами данных через OLE DB Таблица 5-9. Поля структуры (продолжение) Поле для привязки данных параметров. Определяет направ ление передачи данных и может принимать следующие (входной параметр), (выходной параметр), (привязка используется для пара метров). Константы и могут объе диняться логической ИЛИ, если параметр является одно и входным, и выходным Размер памяти, которую должен потребитель для хранения полученных данных Флаги столбца. Набор флажков определен в рамках перечисления Тип данных, расположенных в Максимальная точность численных данных или длина пред ставляющей данные других типов bScale Количество цифр справа от десятичной точки для данных типа или Заполнение массива структур DBBINDING удобно выполнять в цикле.

Перед запуском цикла нам нужно в которой будет храниться номер текущего столбца, а также переменную cbRow для хранения текущего смещения поля в буфере строки:

nCurrentCol;

cbRow = 0;

Чтобы обнулить поля структуры DBBINDING, мы применяем функцию 0, Цикл выглядит следующим nCurrentCol = 0;

nCurrentCol < nColsCount;

!

= cbRow += На каждой итерации цикла помимо увеличения на единицу номера текущей строки nCurrentCol мы извлекаем длину данных текущего столбца из соответ ствующего элемента массива с информацией о наборе данных pColInfo. Эта информация записывается в поле cbMaxLen структуры и используется для увеличения содержимого переменной определяющей смещение данных столбца в буфере.

В теле этого цикла выполняется инициализация других полей массива струк привязки:

= nCurrentCol + = cbRow;

(см. стр.) 250 Базы данных в Интернете. руководство = = = = = = В поле iOrdinal записывается номер текущего столбца, увеличенный на еди Это увеличение необходимо потому, что столбцы с единицы, а начальное значение переменной цикла равно нулю.

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

Для того чтобы возложить задачу памятью на потребителя дан ных, мы записываем в поле константу DBMEMOWNEFLCLIENTOWNED.

Так как наша привязка для работы с набором а не для передачи параметров команде, в поле необходимо записать DBPARAMIO_NOTPARAM.

Инициализация полей bPrecision, bScale и массива pDBBind выполня ется путем переписывания значений из массива pColInfo, со держащего информацию о столбцах набора записей, в результате выполнения команды.

Выполнение привязки данных После подготовки массива с информацией о мы должны выполнить создав объект Для этого мы вначале получаем указатель на интерфейс и сохра няем его в переменной lAccessor* Далее мы создаем массив структур размер которого равен ко личеству столбцов в полученном наборе данных:

pDBBindStatus = NULL;

= new Далее мы передаем количество столбцов в наборе данных, указатель на мас сив pDBBind с информацией о привязке данных, адрес для храпения идентификатора привязки и указатель методу фейса lAccessor на массив структур DBBINDSTATUS:

pDBBind, 0, pDBBindStatus);

Через первый параметр методу CreateAccessor передаются флажки свойств объекта привязки, которые определяют назначение этого объекта, Возможные мы перечислены в таблице 5-10.

Третий параметр метода CreateAccessor задает количество байт в наборе па раметров и не используется при работе с наборами записей. Поэтому для него нулевое значение.

Глава 5. Связь приложений с базами через OLE DB Таблица 5-10. Флажки метода Флажок Описание DBACCESSOR_INVALID Используется методом для того, чтобы сооб щить программе о произошедшей ошибке Объект по ссылке Объект описывает привязку столбцов набора данных DBACCESSOR_PARAMETERDATA Объект предназначен для привязки значений парамет ров команды Создается оптимизированный объект привязки, которая касается использования внутренних буферов Массив структур на который передается CreateAccessor через последний параметр, позволяет отследить результат при для каждого столбца.

Структура как двойное слово, в которое записыва ются флаги результата привязки:

DWORD DBBINDSTATUS;

Эти флажки перечислены в таблице Таблица Флажки результата привязки Флаг Описание DBBINDSTATUS_OK выполнение привязки Неправильно указан номер Провайдер не может данных Неправильное значение параметров в поле структуры параметров привязки Ошибка при установке в поле структуры параметров привязки недоступен интерфейс, необ ходимый для привязки данных Обработка набора записей Теперь, когда привязка мы можем приступить к извлечению данных из набора, созданного в результате выполнения команды.

Эта операция выполняется в тройном вложенном цикле.

Внешний цикл вызывает метод интерфейса как это по казано ниже:

HROW* = { 0, 30, );

== 0) break;

(см. стр.) 252 Базы данных в Интернете. Практическое руководство // Обработка строк NULL, NULL, NULL);

} Первый параметр метода определяет идентификатор оглавления набора записей и в нашем случае равен нулю. Второй параметр задает началь ное смещение при обработке набора записей. Мы обрабатываем набор с самого начала и определяем для этого параметра нулевое значение. третий пара метр мы передаем количество строк, извлекаемых для обработки из набора за писей за один прием (мы задали произвольное значение, равное 30). Если ука зать для этого параметра значение, выборка записей будет выпол няться в обратном направлении (от конца набора записей к его началу).

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

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

char* pRowValues = new for <.

// Обработка полей строки Здесь мы получаем отдельные строки из блока строк, извлеченных только что рассмотренным методом используя для этого массив идентифика торов строк rghRows и метод GetData.

В качестве первого методу GetData передается идентификатор из влекаемой строки. Второй параметр предназначен для передачи идентификато ра объекта привязки.

Данные строки записываются методом GetData в область памяти pRowValues, передаваемой методу GetData через третий параметр. Размер этой области хра нится в переменной Он был вычислен на этапе привязки данных.

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

ULONG = 0;

nCurrentCol < nColsCount;

if Тип хранящихся в поле:

Глава 5. Связь приложений с базами данных через OLE DB // // Данные из текущего поля // В этом цикле мы можем ссылаться как на массив pColInfo, содержащий пол ную информацию о столбцах (имя столбца, тип данных и т. д.), а также на мас сив значений По завершении обработки набора записей Ваша программа должна освобо дить объект привязки и указатель на интерфейс Первая операция выполняется с помощью метода а вторая — методом Release.

Программа OLEDB В качестве примера программы, написанной на языке C++ и обращающейся к базе данных средствами OLE DB, приведем исходные тексты простой утилиты OLEDB, отображающей на консольном экране информацию из таблицы посе clients нашего Интернет-магазина.

Программа получает из базы данных и выводит на экран идентификатор за писи покупателя, его имя, пароль, дату регистрации и электронный почтовый адрес E-Mail;

1 frolov 123 01.12.1999 20:23: 10 petrov 111 05.12.1999 12:02: 12 sidorov 1aa 06.12.1999 13:14: Полные исходные тексты утилиты OLEDB приведены в листинге 5-1.

Листинг 5-1 Вы найдете в файле ch5\oledb\oledb.cpp на прилагаемом к книге компакт-диске.

Рассмотрим эти исходные тексты в деталях.

Глобальные определения В самом начале файла исходных текстов мы определили несколько макросов и включили некоторые Для того чтобы все строки и символы представлялись в кодировке UNI CODE, мы ввели следующие определения:

UNICODE Инициализация констант OLE DB выполняется при помощи определения макроса «define DBINITCONSTANTS И наконец, для работы с глобальными уникальными идентификаторами в приложении определен макрос INITGUID:

INITGUID 254 Базы данных в Интернете. Практическое Помимо обычных для приложений Windows файлов и мы включили в исходный текст файлы msdaguid.h и flinclude Файлы oledb.h и oledberr.h для определений и терфейсов OLE DB, а файлы msdaguid.h и msdasql.h относятся к провайдеру ODBC, использованному нами для создания источника данных.

Для инициализации системы СОМ перед началом работы программы и для освобождения ресурсов СОМ перед завершением программы мы определили в области глобальных переменных уже знакомую Вам предыдущей главе пере менную класса Comlnit:

struct Comlnit { { } До начала работы выполняется СОМ методом а до ее завершения — СОМ методом CoUninitialize, В области глобальных мы также определили три указателя на интерфейсы IMalloc, IDBInitialize и IRowset:

= NULL;

IDBInitialize* pIDBInitialize = NULL;

IRowset* = NULL;

Первый из них используется для памятью, второй — для иници ализации объекта провайдера источника а третий — для работы с извле ченным набором записей.

Функция main Исходный текст получающей управление при програм мы, представлен ниже:

агдс, TCHAR* argv[J, TCHAR* get_records();

else Глава 5. Связь приложений с базами данных через != != NULL) != NULL) } return 0;

В начале своей работы функция main выполняет инициализацию источника данных, вызывая для этого функцию init, определенную в нашей программе.

Если инициализация успешно, main запускает команду, из таблицы clients о В том случае, если команда выполнена без ошибок, функция извле кающая или отображающая в консольном строки таблицы clients.

При каких-либо ошибок в работе программы main освобождает указатели на интерфейсы IMalloc, IDBInitialize и Пред варительно она убеждается в том, что указатели не содержат нулевые значения.

Перед указателя па интерфейс мы вызываем ме тод Uninitialize, освобождающий ресурсы, полученные программой при ини циализации источника данных.

Функция init Перед тем как приступить к инициализации источника данных, функция init получает для системы СОМ, вызывая для этого функцию return false;

В результате в глобальную переменную записывается указатель на интерфейс системы управления памятью СОМ. может использо вать этот указатель для вызова методов интерфейса IMalloc, таких, как Realloc, Free и т. д. Память, полученная таким образом, применяется в много поточной среде.

Наша программа заказывает неявно, обращаясь к интерфейсам OLE DB, однако, прежде чем работу, функция get_records вызывает тод Free IMalloc для заказанной для описа ния столбцов набора записей.

Дальнейшие функцией init, мы описали в начале этой Вначале функция создает объект IDBInitialize и получает на со интерфейс:

256 Базы данных в Интернете. Практическое NULL, if (pIDBInitialize == return false;

Далее функция init готовит массив свойств и, пользуясь указателем на интерфейс IDBInitialize, выполняет инициализацию источника данных:

= VT_I2;

= = = VT_BSTR;

= = = = 4;

= • • • = return false;

Здесь мы привели только фрагмент кода, установку свойств, необходимых для инициализации.

Обратите внимание, что перед вызовом метода инициализации наша програм ма освобождает память, для переменных типа BSTR:

После установки значений свойств переменные уже не нужны.

Функция Функция startCommand предназначена для создания а также создания и запуска команды.

Так как мы уже достаточно подробно описали этот процесс, то не будем по вторяться. Отметим только, что запускает SELECT, вы бирающую из таблицы покупателей clients поля с именами ClientID, Password, RegisterDate и Email:

LPCTSTR = ClientID, UserlD, Password, RegisterDate, Email FROM Глава 5. Связь приложений с базами данных через OLE DB Функция get_records Методику, использованную нами в этой функции для извлечения и обработки записей набора, полученного в результате выполнения команды SELECT, мы опи сали очень Здесь же мы остановимся только на процессе получения данных из полей текущей записи и на выполнении преобразования типов для на консоль.

Обработка полей текущей строки выполняется в цикле:

= 0;

< { == { !

else == I I ts = ts->day, ts->year, Программа выводит консоль данные в текстовом виде, однако извлекае мые данные могут иметь различный тип в зависимости от столбца. Прежде чем преобразование, мы определяем тип данных в текущем столбце, ана лизируя соответствующий элемент массива описания столбцов Тип данных записан в поле wType.

Для разработки кода, выполняющего преобразование, Вам помогут данные из таблицы 5-8. Анализируя содержимое поля wType, Вы сможете выбрать подхо дящий способ преобразования.

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

Если же столбец таблицы содержит числовое значение DBTYPE_I4, мы исполь зуем в функции pri ntf другой спецификатор формата и передаем данные не через указатель, а непосредственно.

дело обстоит с данными типа содержащими отметку о времени. Для того чтобы получить отдельные составляющие такой отметки, мы определили в своей программе указатель ts типа DBTIMESTAMP. Да лее мы записываем в него значение адреса поля данных с временной отметкой 258 Базы данных в Интернете, руководство и обращаемся к полям структуры для отображения даты регистра ции посетителя в форматированном виде.

чем завершить работу, удаляет заказанные мас сивы и освобождает память, полученную для буферов:

delete [] delete [] delete [] Использование библиотеки шаблонов ATL Как показано в примере из предыдущего раздела, прямое использование объект ного интерфейса OLE DB разработчика вникать во множество дета лей, имеющих к технологии применения модели объекта СОМ. Например, Вам придется образом получать указатели на интерфейсы, а потом заботиться об их освобождении, проверять коды заверше ния методов и функций, сложные взаимосвязанные структуры для привязки данных и т. д.

Однако те из Вас, кто пользуется для создания приложений системой про граммирования Microsoft Visual C++ версии 6.0 или более новой, получают воз можность заметно сократить кода, не имеющего отно шения к выполнению операций с базой данных, а. значит, сконцентрироваться на решении своей Такую возможность предоставляет биб лиотека шаблонов ActiveX Template Library (ATL).

Она существенно как создание новых элементов управления ActiveX, так и использование готовых элементов управления ActiveX, к которым можно отнести объекты OLE DB. этой библиотеки обеспечивают про стой доступ к возможностям OLE DB, упрощают процесс привязки данных на боров и параметров процедур, а также допускают использование есте типов данных, C++.

Создавая приложения OLE DB с использованием библиотеки шаблонов ATL, Вы должны применять для работы с источником данных специальный набор классов. Его мы рассмотрим в этом разделе. Эти классы скрывают внутреннюю сложность обращения к объектам OLE DB, в распоряжение про граммистов относительно простой набор методов и свойств.

Для использования этих классов в исходные тексты Вашего приложения включить оператором файл Класс CDataSource Этот класс инкапсулирует в себе соединение с объектом источника OLE DB. В рамках этого соединения приложение может создавать один или несколь ко С применением класса CDataSource источника выпол так же легко, как и в серверных сценариях, обращающихся к объектам Глава 5. Связь приложений с базами данных через OLE dsDSN;

hr = "Bookstore", // Обработка ошибки Все, что Вам нужно сделать для создания соединения, — вызвать метод Open класса В данном классе имеется несколько перегруженных определе ний Open, позволяющих указывать или только некоторые параметры.

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

При необходимости Вы сможете передать эти параметры и через структуру DBPROPSET, применяя другой вариант определения метода Open.

Когда работа с данных его нужно закрыть, вызвав метод Close класса CDataSource:

В классе CDataSource определено еще несколько методов, которые мы не используем в книге. К ним методы GetProperties и GetProperty, предназначенные для свойств соединения с провайдером, метод Getlnitializationstring, позволяющий получить строку инициализации источ ника данных (включая пароль) и другие методы, предназначенные для с источником Класс CSession Для создания сеанса, необходимого для работы с командами и запи Вы должны использовать класс CSession.

Это очень просто:

CSession sSession;

= :

// Обработка ошибки Вам необходимо вызвать метод Open класса передав ему в качестве параметра ссылку па открытый объект класса CDataSource.

работы с данных приложение должно закрыть все открытые сеансы методом Close:

Помимо методов Open и Close, в классе CSession определено несколько мето дов для работы с транзакциями. Это StartTransaction (начало транзакции), 260 Базы данных в Практическое руководство Commit (фиксация транзакции), Abort (отмена и (получение информации о транзакции).

Класс Класс CCommand обеспечивает методы выполнения команд. Он определен следующим образом:

template

public public public TMultiple Здесь класс TAccessor представляет собой класс объекта привязки Accessor, с которым мы уже имели дело в главе, TRowset — класс набора записей, создаваемого при выполнении и который используется с командами, возвращающими одновременно несколько Несмотря па устрашающий вид определения класса пользоваться им достаточно просто. Вот как мы создаем объект этого класса:

CCommand > cmd;

Здесь мы ссылаемся на класс tabClients, в нашем приложении для выполнения привязки данных:

class tabClients ( public:

TCHAR TCHAR DBTIHESTAMP m_RegisterDate;

TCHAR };

Этот класс определяет всю информацию, необходимую для выполнения при вязки. Фактически он содержит описание полей набора который будет образован после выполнения запроса к базе данных. В нашем случае это ца clients, входящая в состав базы данных Интернет-магазина, о которой мы уже рассказывали ранее (поэтому, кстати, мы и выбрали для класса привязки имя tabClients), Заметьте, мы не создаем объектов класса tabClients, нам нужно только определение.

Глава 5. Связь приложений с базами данных через OLE В классе tabClients мы расположили определения сделанные с при менением обычных типов данных C++. Кроме этого, в этом классе есть описа ние столбцов набора записей, сделанное при помощи макрокоманд BEGIN_CO и единственный параметр макрокоманде нужно указать имя класса привязки. В нашем случае это tabClients.

Макрокоманда предназначенная для выполнения привязки данных, имеет два — номер столбца и имя поля данных записи.

И наконец, макрокоманда закрывающая определение столб цов набора, не имеет параметров.

Для того чтобы запустить команду на выполнение, Вы должны воспользо методом Open, определенным в классе TCHAR "SELECT Password, Email FROM clients";

= { // Обработка ошибки Этот метод очень прост в Достаточно передать ему в качестве первого параметра ссылку на открытый сеанс, а в качестве второго — адрес тек стовой строки команды, подлежащей выполнению.

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

== S_OK) I // // // // // Здесь мы перебираем записи образованного набора с помощью метода определенного в классе CCommand.

Для доступа к значениям полей достаточно просто сослаться на соответству ющие поля класса CCommand. Это возможно благодаря применению библиотеки шаблонов ATL.

По завершении цикла обработки записей должно закрыть объект класса сеанс и соединение с источником данных. Все это делается ме Close соответствующих классов:

dsDSN.CloseO;

262 Базы данных в Интернете. Практическое руководство Программа ATLOLEDB Для демонстрации простоты объектного интерфейса OLE DB с библиотеки шаблонов ATL мы подготовили консольную програм му ATLOLEDB, Она решает ту же задачу, что и предыдущая, рассмотренная в — отображает содержимое нескольких полей таблицы регистрации посетителей Интернет-магазина clients.

Полный исходный текст программы ATLOLEDB Вы найдете в листинге 5-2.

Листинг 5-2 хранится в файле на прилагаемом к кни ге компакт-диске.

Глобальные определения Для того чтобы использовать шаблоны предназначенные для работы с объектами OLE DB, мы включили в исходный текст нашего приложения файл Так как наша программа выводит результаты на консоль и при этом пользу ется манипуляторами ввода/вывода, мы включили файлы и flinclude ttinclude Кроме того, для применения необходимо подключить пространство имен std:

using std;

В области глобальных определений мы расположили класса привязки переменных к набору записей class tabClients { public:

TCHAR TCHAR TCHAR DBTIMESTAMP m_ClientIO) m_Email) };

О назначении и внутреннем этого класса мы рассказывали ранее.

Помимо этого, в области глобальных определений мы три объекта Глава 5. Связь приложений с базами данных через OLE DB CDataSource > cmd;

Объект dsDSN используется соединения с источником данных, объект sSession нужен для образования сеанса, а объект cmd — для выдачи ко манды и обработки результата се выполнения.

Функция main Наша программа настолько проста, что все свои действия она в рам ках единственной функции В начале своей работы программа выполняет СОМ, вызы вая для этого функцию CoInitialize(NULL);

Заметим, что освобождение поэтому при использовании ATL CoUninitialize вызывать не надо (и нельзя).

После инициализации пата программа открывает источник данных и сеанс:

= "Bookstore", return 1;

= { return 1;

Б случае возникновения программа завершает свою работу с кодом возврата Далее программа команду:

TCHAR = "SELECT ClientID, Password, RegisterDate, Email FROM clients";

hr = { dsDSN.CloseO;

return 1;

} В качестве команды мы используем строку SQL, запрос к таб лице clients.

набора, образованного в результате этой обра батываются в цикле:

264 Базы данных в Интернета. Практическое == :

cout cout cout ts cmd.m_RegisterDate;

cout szBuf Здесь мы просто выводим значения в выходной поток cout.

выполняя форматирование манипуляторами ввода/вывода (установку ширины колонки и Что же касается форматирования поля даты регистрации, то здесь мы при менили уже Вам трюк, связанный с структуры DBTIMESTAMP. Создав переменную ts типа DBTIMESTAMP, мы в нее значе ние, полученное из поля Далее мы выполняем преобразо вание формата, обращаясь к полям переменной ts.

Перед завершением своей работы программа закрывает объект команды, се анс и соединение с источником данных:

Связь приложений с базами данных через ODBC Последний метод доступа, о мы расскажем в нашей книге, это Microsoft Database Интерфейс ODBC представляет собой набор для доступа к базам данных функций программного интерфейса. Этот набор предполагает использование языка запро сов SQL.

Для того чтобы интерфейс ODBC стал доступен программам, необходимо установить драйвер ODBC. Такой драйвер имеется в составе Microsoft SQL Server, а также в составе многих других СУБД, рассчитанных на работу в среде операционных систем Microsoft Windows, Macintosh и некоторых версий Unix.

При создании приложений с базами данных для Интернета интерфейс ODBC пригодится Вам для связи расширений сервера Web (таких, как программы CGI и ISAPI) с базами данных. При этом вызов функций ODBC будет как непосредственно из программ расширений, так и через дочер ние запускаемые расширениями для обращения к базам данных (это иногда требуется для устойчивости сервера Web к программным ошибкам, при обращении к базе данных).

что в отличие от ADO, интерфейс ODBC не является объектным.

Поэтому он недоступен из сценариев JScript и Script, расположен ных в страницах ASP.

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

Программный интерфейс ODBC В этом разделе речь пойдет о и параметрах функций про граммного ODBC.

Помимо этих функций, обеспечивающих прямой доступ к ODBC, корпора ция Microsoft разработала ряд программных интерфейсов и классов, предназна ченных для обращения к ODBC. Это такие интерфейсы, как RDO и а так же классы MFC и 266 Базы данных в Интернете. руководство Интерфейсы и образом для создания приложений Visual а классы MFC и DAO для создания приложений на основе Microsoft Visual C++, к тому же имеющих интерактивный пользователя.

При разработке приложений Интернета для интерактивной части проекта обычно применяется технология ASP, серверные сценарии и ADO, о чем мы подробно рассказывали в первых главах нашей Что расши рений сервера Web, то они не никакого непосредственного интерфейса Поэтому классы MFC и ориентированные на автоматизи рованное создание диалоговых приложений средствами Microsoft Visual C++, не окажут Вам заметной Именно мы расскажем Вам только о ODBC.

Структура ODBC Программа, к базам данных посредством ODBC, обычно выполняет следующие действия:

инициализирует среду нения;

4 к источнику данных;

создает и результат выполнения команды;

освобождает ресурсы, полученные для работы с ODBC.

Если команда предназначена для выполнения хранимой процедуры, прило жение должно входных и выходных параметров этой про цедуры (а также при необходимости и кода завершения процедуры) к локаль ным переменным, определенным внутри тела Обработка результата также связана с привязкой к локальным пере менным. Вы уже с этой процедурой из предыдущей главы, посвящен ной интерфейсу OLE Хотя приложения ODBC выполняют эту по-другому, смысл ее не меняется — устанавливается между ло кальными переменными и полями набора записей, полученных при выполнении SQL.

Нетрудно заметить, что мы говорили о тех же самых действиях, что применяются для работы с базами данных, но выполняемых посредством мето дов доступа ADO и OLE DB. Действительно, набор действий остается тем же самым. Меняется только способ их реализации.

Рассмотрим назначение функций ODBC, вызываемых на различных этапах работы приложения ODBC.

Инициализация Для выполнения инициализации среды выполнения ODBC исполь такие как SQLAllocHandle и Первая из них отвеча ет за собственно а вторая позволяет параметры среды исполнения.

Вот функции SQLAllocHandle:

hType, SQLHANDLE* Глава 6. Связь приложений с базами данных через ODBC В качестве параметра функции тип идентификатора. Это может быть идентификатор иденти фикатор соединения с источником данных идентификатор стро ки или дескриптора параметр в каком контексте нужно получить идентификатор, Здесь могут быть указаны константы LE_ENV или И наконец, третий параметр адрес в которую сывается идентификатор, полученный функцией SQLAllocHandle.

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

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

SQLFreeHandle hType, SQLHANDLE Через первый параметр функции SQLFreeHandle передается тип идентифика тора (такой же, как и SQLAllocHandle), а через второй — освобождае мый идентификатор.

Инициализация среды выполнения Рассмотрим кода приложения, выполняющий инициализацию среды для запроса к базе данных.

Прежде всего должна получить идентификатор среды типа SQL_HANDLE_ENV:

SQLHENV = SQL_NULL_HENV;

RETCODE гс = SQL_NULL_HANDLE, Он записывается в переменную На следующем этапе нам нужно установить атрибуты в частности указать номер версии ODBC, равный 3. В результате приложение сможет вос пользоваться особенностями этой версии драйвера. Так, драйвер ODBC будет работать с кодами даты и времени SQL SQL_TY также возвращать коды SQLSTATE при ошибок.

Атрибуты среды с помощью функции SQLSetEnvAttr, име ющей четыре параметра:

= 268 Базы данных в Интернете. Практическое первый параметр этой функции передается идентификатор для которой выполняется настройка атрибутов.

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

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

Смысл параметра от типа значения атрибута, мого через третий параметр. значение числовое (как в нашем случае), чет вертый параметр определяет тип значения атрибута, а если — длину Инициализация среды для установки соединения На втором этапе инициализации Вам получить идентификатор соединения типа который создается в только что созданного иден тификатора среды hDbC = SQL_NULL_HDBC;

= Обратите внимание, что мы передаем значение функции SQLAllocHandle че рез второй параметр идентификатор имеющий тип Теперь, после выполнения второго этапа инициализации, у нас уже есть два — hEnv (идентификатор среды выполнения) и hDbc (идентифи катор среды соединения).

Установка Для установки соединения с источником данных Вам придется воспользовать ся прототип которой приведен hConnection, * SQLSMALLINT ServerNameLength, SQLCHAR * UserNameLength, SQLCHAR * Password, SQLSMALLINT Через первый параметр hConnection SQLConnect передается иденти фикатор соединения типа на втором этапе иници ализации, Второй параметр ServerName определяет имя сервера, в виде тексто вой а третий (с названием — длину этой строки. Ана логично UserName и Password задают имя пользователя и его пароль, а параметры UserNameLength и PasswLength — размер строк имени пользователя и пароля.

Вот фрагмент текста выполняющий с источником данных BookStore:

+ 1] = "BookStore";

= UCHAR = = szDSN, Глава 6. Связь приложений с базами данных через ODBC (const В случае успешного соединения функция вернет SQL_SUC CESS или а при ошибке - значение или Подготовка и запуск команды Программный интерфейс ODBC возможностей для команд, однако, мы рассмотрим только один, связанный с использованием SQLExecDirect.

команды с применением функции состоит из двух этапов.

На первом нужно создать команды типа а на втором — выполнить команду, SQLExecDirect.

Получение идентификатора команды Получение идентификатора команды реализуется обычным способом с приме нением = гс = hDbc, fchStmt);

Обратите внимание на то, что идентификатор команды создается в контек сте идентификатора соединения типа поэтому через второй па раметр мы перелаем функции SQLAllocHandle значение hDbc. Идентификатор hDbc был на этапе инициализации.

Запуск команды Для команды на надо вызвать функцию про тотип которой расположен ниже:

SQLINTEGER Через первый параметр этой функции передается идентификатор команды типа второй — строка команды, а через третий — команды.

Если команда выполнена без ошибок, функция значение или а при значение SQL_INVALID_HANDLE или что Вы получите воз врата И SQL_NEEO_DATA возвращается при использовании так называемых параметров времени parameter). Такой тип пара метров предполагает использование для данных функций SQLParamData и SQLPutData. Мы в своих не будем применять параметры исполнения.

Значение возвращается при команд, не вызывающих создания наборов записей. К ним относятся, например, команды уда ления или обновления строк.

А сейчас мы покажем пример вызова команды, выполняющей выборку полей Name, Password, и Rights из таблицы managers:

270 Базы данных в Практическое гс = (unsigned "select Name, Password, Rights managers", В качестве длины строки, через послед ний параметр, мы указали Эта константа означает, что дли на строки закрывающим ее двоичным нулем. нам не надо определять длину строки команды явным образом при помощи такой как Обработка результата выполнения команды Если в результате выполнения команды создан набор записей, программа может его получить посредством соответствующих функций интерфейса ODBC. Од нако перед тем как это сделать, она должна выполнить привязку полей набора к локальным переменным, определенным программы.

Привязка полей к локальным переменным Такая выполняется функцией VariableType, VariableValuePtr, BufferSize, SQLINTEGER* cbSize);

Параметр hStatement задает идентификатор команды, для которой выполня ется привязка. Это как раз тот с использованием которого фун кция выполняла команду.

Через передать номер набора данных, созданного в результате выполнения команды. Если в наборе нет стол бца bookmark, то нумерация выполняется, единицы, а если есть — то с нуля.

Параметры VariableType и Vari abl eVal uePtr задают тип ло кальной переменной, для которой привязка, и этой локаль ной С помощью параметра необходимо указать размер области памя ти, отведенной для локальной переменной с адресом VariableValuePtr (с учетом двоичного нуля, закрывающего текстовую строку). Это значение используется драйвером ODBC в качестве ограничителя, для тою чтобы избежать дан ных за пределами Такая ситуация иногда возникает при извлечении из базы данных содержимого полей переменной длины.

Значение параметра при данных в ные длины типа целых чисел.

Параметр cbSize бывает как входным, так и выходным. Он задает адрес ременной, в которую размер данных, функцией из записей SQLFetch (или Функция использует этот параметр как входной.

В качестве примера приведем фрагмент кода, выполняющего привязку го числового поля, одного текстового поля и одного поля, содержащего отмет ку о Глава 6. Связь приложений с базами данных через ODBC Локальные переменные, которые привязаны к определены так;

+ Мы выполним привязку к полям таблицы managers с именами Name Вот фрагмент кода для первого из SQLINTEGER гс = 1, Здес]. выполняется привязка поэтому мы передаем функции через второй параметр значение 1. Константа задает тип данных, соответствующий стандартному типу С «long int>>. Константы для Вы найдете в таблице 6-1.

Хотя мы и в пятом параметре размер области памяти, выделенной для переменной nManagerlD, он будет проигнорирован, так как тип область памяти размера.

Привязка переменной в которую будет записана текстовая выполняется аналогично:

SQLINTEGER CbName;

гс = SQLBindCoKhStmt, 2, szName, MAXNAME, Здесь мы указали данных соответствующий типу данных С Константа MAXNAME длину буфера, не позволяя драйверу ODBC выйти за его в процессе записи данных из поля Name.

Для привязки поля LastLogin (содержащего отметку о дате и времени по следнего подключения), мы указали тип данных SQLINTEGER cbLastLogin;

гс = SQLBindCoKhStmt, 3, Значение, нами в пятом параметре, будет Мы его только общности.

В таблице мы перечислили идентификаторы типов, передаваемых функ ции SQLBindCol, для разных типов Там же Вы найдете и типы данных ODBC, которые потребуются при вызове хранимых процедур SQL Server.

Таблица типов данных С и ODBC Тип данных С Идентификатор char SQL_C_STINYINT unsigned char SQL_C_BIT SQLCHAR unsigned char* SQLCHAR* Short int short int SQLUSMALLINT long SQLINTEGER Базы данных в Интернете. Практическое руководство Таблица Идентификаторы типов данных С и ODBC (продолжение) Тип данных С Идентификатор Тип данных ODBC unsigned long int SQLUINTEGER BOOKMARK float double SOLFLOAT _int64 SQLBIGINT unsigned _int SQL_C_TYPE_TIME SQL_C_TYPE_TIMESTAMP SQL_C_GUID SQLGUID В таблице есть ссылки на типы данных TAMP_STRUCT, и SQLGUID. Эти структуры предназначены для представления даты, времени, отметки о числовых значений и глобаль ных уникальных Для удобства ниже мы приводим их struct tagDATE STRUCT SQLSMALLINT year;

// год SQLUSMALLINT month;

// месяц SQLUSMALLINTday;

// день } struct ' SQLUSMALLINT hour;

// чась SQLUSMALLINT minute;

// минуты SQLUSMALLINT second;

// секунды Struct tagTIMESTAMP_STRUCT I SQLSMALLINT year;

// год SQLUSMALLINT month;

// месяц // день SQLUSMALLINT hour;

// часы SQLUSMALLINT minute;

// минуты SQLUSMALLINT // секунды SQLUINTEGER fraction;

// доли секунды } tagSQL_NUMERIC_STRUCT precision;

// точность Глава 6. Связь приложений с базами данных через SQLSCHAR scale;

// масштаб SQLCHAR sign;

// знак // значение } struct DWORD WORD Data2;

WORD Data3;

BYTE } Цикл обработки записей После того как Ваше приложение привязку оно может ступать к извлечению записей набора, результате выполнения команды.

Эта операция выполняется в простом цикле, ниже:

= != !

// szPass, // // Здесь для извлечения очередной записи набора мы использовали SQLFetch. В параметра этой функции передается иден тификатор команды.

Когда все записи набора будут получены, SQLFetch вернет значение SQL_NO_DATA. Это ее свойство мы использовали для завершения цикла. Вы так же можете усовершенствовать цикл, прерывая его работу в случае возникнове ошибок.

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

Обработка ошибок Как мы уже говорили, в случае возникновения ошибок функции ODBC возвра щают значения, такие, как или SQL_ERROR. Однако в большин стве случаев такой информации недостаточно.

Для того чтобы получить развернутое описание ошибки, необходимо запро сить у драйвера ODBC диагностические записи. Эта операция выполняется с применением функции SQLGetDiagRec. Отдельные поля диагностических запи сей извлекаются при помощи функции Извлечение диагностических записей Логика обработки ошибок, рекомендуемая в предполага ет, что получения диагностических записей всякий раз, когда функции ODBC возвращают от Однако 274 Базы данных в Интернете. руководство в некоторых случаях Вы можете дополнительные информаци онные сообщения, возникающие при коде возврата не рассматривая данную ситуацию как ошибочную, Так как с одной ошибочной ситуацией иногда связано несколько диагности ческих записей, функция SQLGetDiagRec должна извлекать эти в цикле.

Рассмотрим прототип функции hType, SQLSMALLINT SQLCHAR* SQLCHAR* SQLSMALLINT SQLSMALLINT* Через параметр hType Вы тип для которого нуж но получить диагностику. Здесь Вы можете указать хорошо знакомые значения SQL_HANDLE_DBC, и если при выполнении команды, должен со держать тип идентификатора команды если при создании со единения с данных — тип SQL_HANDLE_OBC, и т. д.

Параметр hHandle используется для передачи самого идентификатора.

Через параметр nRecord Вы передать номер извлекаемой записи.

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

Параметр SQLState указатель на буфер, в который записы вается код состояния SQLSTATE. Первые два в этом буфере указывают класс состояния, а три — подкласс. Подробную информацию о ко дах состояния Вы найдете в на Microsoft SQL Server.

Через параметр pNativeErrorPtr необходимо передать указатель на буфер, в котором будет храниться естественный код ошибки, зависящий от источника данных.

Текст об ошибке записывается в буфер, адрес которого передает ся функции SQLGetDiagRec через параметр pMessageText. Размер этого буфера должен быть указан с помощью параметра И последний параметр pcbText используется для передачи указате ля на переменную, в которую будет записана длина упомянутого выше сообще ния об ошибке.

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

RETCODE = = OL;

SWORD = 0;

szSQLState[256] = = SQLSMALLINT 6. Связь с базами данных через ODBC гс = 255, :

Записи состояния Указанным выше методом можно получить из двух типов ких записей, а именно заголовка. при возникновении любых кроме тех, что вызывают кода завершения При использовании ODBC версии 3.x становятся доступными диагностические записи называемые записями состояния. Они генерируются отдельно для каждой записи заголовка и могут быть посредством функции SQLGetDiagField:

SQLGetDiagField( SQLSMALLINT nRecord, SQLSMALLINT SQLSMALLINT SQLSMALLINT* Через первый параметр hType Вы должны передать функции SQLGetDiagField •сип для которого нужно получить диагностику. Это ты SQL_HANDLE_ENV, и SQL_HANDLE_DESC.

Параметр hHandle для передачи идентификатора.

Через параметр функции SQLGetDiagField передают номер записи заголовка, для которой извлекаются записи состояния. Это тот самый номер, что переда ется через одноименный параметр функции SQLGetDiagRec.

Параметр nDiagld позволяет указать идентификатор извлекаемой записи со стояния и задастся в виде одной из констант.

С помощью параметра pDiaglnfo Вы передать функции указатель на буфер, к которую будет диагностическая информация. Размер этого буфера задается параметром nBufferSize. nBufferSize в том если указатель pDiaglnfo ссылается на буфер данных фиксирован ного размера.

Для текстовых строк допускается также указывать в nBufferSi ze константу SQL_NTS. Она означает, что буфер содержит текстовую строку, закры тую двоичным И наконец, в переменную, адрес которой задается параметром pStringSize, записывается символов в диагностическом сообщении (без учета двоичного нуля, текстовую строку).

Вот фрагмент программы, в котором для записи заголовка извлекаются за писи состояния:

276 Базы данных в Интернете.

гс = nRecordNumber, 255, &pcbErrorMessage);

< = nRecordNumber, NULL);

= sqlhHandle, nRecordNumber, NULL);

= SQLGetDiagField(nHandleType, sqlhHandle, SQL_DIAG_SS_MSGSTATE, NULL);

= nRecordNumber, NULL);

= sqlhHandle, nRecordNumber, = sqlhHandle, nRecordNumber, SQL_DIAG_SS_SRVNAME, Здесь используются константы, перечисленные в таблице 6-2.

Таблица 6-2. Идентификаторы типов данных С и ODBC Константа Номер строки в наборе записей или номер параметра в на боре параметров, с которым связана данная запись Имя процедуры, вызвавшей ошибку Номер строки в процедуре, вызвавшей появление ошибки SQL_DIAG_SS_MSGSTATE Значение состояния, полученное от оператора RAISERROR Степень тяжести ошибки SQL_DIAG_SS_SRVNAME Имя на котором произошла данная ошибка Программа ODBCAPP Программа ODBCAPP, исходные тексты которой мы описываем в этом ле, выводит на консольный экран все записи из файла managers базы данных нашего Интернет-магазина:

1 | frolov | 123 | Administrator | 21.12.1999 11:24: 2 | Petrov 123 | | (not logged yet) | Sidoroff 123 | Sales_manager | (not logged yet) 5 | j 1234 | Sales_manager | (not logged yet) 4 | admin | 123 | | 05.12.1999 09:50: Глава 6. Связь приложений с базами данных через ODBC Полные исходные программы ODBCAPP находятся в листинге 6-1.

Листинг Вы найдете в файле ch6\odbcapp\odbcapp.cpp на прилагаемом к книге компакт-диске.

Глобальные определения и константы Для к функциям и константам программного интерфейса ODBC мы включили в исходные тексты нашего приложения четыре файла:

ffinclude Для формирования строки сообщения об ошибке используется шаблон из стандартной библиотеки шаблонов Поэтому в исходном тексте мы сде лали такие определения:

using namespace В области глобальных переменных задали SQLHENV = hDbc = В hEnv хранится идентификатор среды исполнения, в перемен ной hDbc — идентификатор с источником данных, а в переменной hStmt - идентификатор команды.

Функция main Функция main выполняет установку соединения, создание и команды, извлечение и на экран результатов ее В области переменных функции main мы определили переменную гс, для кода возврата функций программного интер фейса ODBC, три строки, необходимые для подключения к данных (содержащих имя им пользователя и а также стро ку класса string для хранения сообщения об + 1] = = UCHAR = string sErrMsg;

Получив функция main среду выполнения граммы, получая соответствующие идентификаторы:

гс = NULL, != return = SQLSetEnvAttr(hEnv, (см. стр.) 278 Базы данных в Интернете. Практическое руководство != гс return 1;

гс = != && return 1;

Обратите внимание, что пока мы не установили соединение с источником данных, обработка ошибок заключается в простом завершении с кодом 1. в том, что на данном этапе средства расширенной диагностики ошибок доступны.

Далее программа устанавливает соединение с данных:

= szDSN, char*)szDSN), != && !

{ return • Если функция SQLConnect вернула код ошибки, мы вызываем функцию GetEr определенную в нашей программе. О ней мы поговорим позже, а сейчас только скажем, что эта функция извлекает заголовки диагностических записей и формирует из них текстовую строку которая затем отображается на консольном экране.

В том случае, если функции main удалось открыть соединение с источником данных, она создает идентификатор команды и запускает команду на выполнение:

гс = hDbc, != hDbc, sErrMsg);

1;

= (unsigned "select Name, Password, Rights from managers", != != SQL ;

sErrMsg);

return 1;

6. Связь приложений с базами данных через ODBC В качестве команды мы простой оператор SELECT, ющий несколько полей из таблицы managers.

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

Следующий этап — привязка локальных переменных к полям набора извлеченных в результате команды:

SQLCHAR + SQLINTEGER szPass[MAXNAME + SQLINTEGER cbPass;

SQLINTEGER SQLCHAR + SQLINTEGER !

= 1, = SQLBindCoKhStmt, 2, MAXNAME, = SQLBindCoKhStmt, 3, szPass, MAXNAME, &cbPass);

= SQLBindCoKhStmt, 4, = SQLBindCoKhStmt, 5, szRights, MAXNAME, мы последовательно привязываем пять локальных переменных nMana gerlD, szName, szPass, tsLastLogin, szRights к столбцам набора записей с имена ми Password, LastLogin, Rights соответственно. В этой главе мы уже о том, как выполнить привязку данных с SQLBindCol.

После выполнения привязки функция main запускает цикл извлечения запи сей из полученного в результате выполнения = != I < 0) | | | | (not logged nManagerlD, szName, szPass, szRights);

else I | | | | nManagerlD, szName, szRights,.

280 Базы данных в Интернете. Практическое Записи средствами В теле мы выво дим на консоль содержимое полей.

Так как LastLogin (дата подключения сотрудника магазина) может содержать значения NULL, мы обрабатываем этот случай При знаком пустой записи NULL является значение пере менной содержащей размер извлеченных данных.

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

Вначале программа освобождает идентификатор команды, вызывая для это го функцию Далее от данных при помощи функции И наконец, мы освобождаем идентификаторы соединения и среды исполнения:

Функция Эта функция выполняет извлечение заголовка диагностической записи, а так же полей записей состояния, созданных для данной диагностической записи.

Алгоритм извлечения записей мы уже рассматривали.

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

!= I гс = SQLGetDiagRec(nHandleType, 255, SQL_NO_DATA_FOUND) { = sqlhHandle, nRecordNumber, SQL_IS_INTEGER, NULL);

= sqlhHandle, nRecordNumber, SQL_DIAG_SS_LINE, NULL);

= SQLGetDiagFieldCnHandleType, sqlhHandle, nRecordNumber, SQL_DIAG_SS_MSGSTATE, NULL);

= SQLGetDiagField(nHandleType, sqlhHandle, nRecordNumber, NULL);

= sqlhHandle, nRecordNumber, SQL_DIAG_SS_PROCNAME, Глава 6. с базами данных через ODBC гс = = "SQL State:

+= sErrMsg += Error:

sErrMsg += sErrMsg Message:

sErrMsg sErrMsg += Row Number:

sErrMsg += += State:

+= sErrMsg += sErrMsg += sErrMsg += sErrMsg += Name:

sErrMsg += Заголовок диагностической записи извлекается функцией Далее при помощи функции извлекаются по очереди значения записей состояния. Среди них есть как численные значения, так и текстовые Для формирования общей строки сообщения об ошибке мы преобразу ем численные значения в строки и добавляем к строке sErrMsg, ссылка на кото рую передается функции Вот какая строка формируется в том случае, если мы допустили синтаксичес кую ошибку в операторе SELECT, указав, его как SELECTT:

Error SQL State: Native Error: Error Message: SQL Server Server]Incorrect synta x near the keyword ODBC Row Number: Message State: Severity: (см. стр.) 282 Базы данных в Интернете. Практическое Server Name:

Если ошибка — в имени текст сообщения будет другим:

Error SQL State: 42S Native Error: Error Message: SQL Server column name ODBC Row Number: Message State: Severity: Proc Name:

Server Name: FROLOV Как видите, диагностика ошибки достаточно Функция Она вызывается для обработки возникающих на ранней стадии рабо ты программы до момента установления с данных.

Внутри этой находится цикл, котором заголовки диагностических записей при функции SQLGetDiagRec:

!= SQL_NO = SQLGetDiagRec(nHandleType, sqlhHandle, 255, = "SOL State:

sErrMsg += sErrMsg += Error:

sErrMsg += (LPSTR)szBuf;

sErrMsg += Message:

sErrMsg += (LPSTR)szErrorMessage;

} Эта функция также формирует в sErrMsg итоговое сообщение об Бог, например, какое сообщение появится на экране, указать неправиль ное имя источника данных:

error SQL State:

Native Error: Error Message: Driver Manager] Data source name not found and no default driver specified Глава 6. Связь с данных через ODBC Запуск хранимых процедур Как уже говорилось хранимых упростить разработку и с базами данных за счет отделения грамм от данных.

Практически при создании приложений для Интернета или Вам вызвать хранимые процедуры из серверных сценариев JScript или Script, встроенных в ASP, либо из расширений сервера таких, как программы CGI или 1SAPI. В последнем случае мы дуем обращаться к бале данных Microsoft SQL Server с интерфейса ODBC, а не ADO или OLE DB.

Именно поэтому, рассказывая о работе с методами доступа ADO и OLE DB в приложениях, написанных на C++, мы опустили материал о хранимых процедур как второстепенный. же необходимо к нему вернуться, так как уже в следующей главе мы займемся созданием расширений сервера Web, обра щающихся к базам данных через ODBC.

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

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

Для параметров процедур Вы использовать SQLBindParameter, которой приведен SQLSMALLINT nParameterType, SQLSMALLINT SQLINTEGER SQLINTEGER* Через параметр hStatement программа должна передать SQLBind Parameter созданный идентификатор команды запуска процедуры.

Параметр задает номер параметра процедуры, который будет привязан к локальной переменной. Нумерация параметров начи нается с единицы.

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

284 Базы данных в Интернете. руководство Параметр определяет идентификатор типа данных С локальной привязываемой к параметру. Здесь можно указывать такие констан как или Полный список идентификаторов приве в таблице Тип параметра хранимой процедуры указывается через параметр пРага функции Здесь указываются такие типы данных SQL, как или (см. 6-1).

Параметр определяет максимальное количество символов, цифр или точность передаваемых через параметр.

С параметра программа задаст количество десятич ных цифр маркера Через параметр программа передает функции SQLBi nd указатель на буфер локальной переменной, которая должна быть при вязана к параметру хранимой процедуры. Длина этого буфера определяется параметром И наконец, через параметр Вы передаете указатель на в которую предварительно была записана длина параметра.

В следующем фрагменте кода мы выполняем привязку двух входных пара метров и одного выходного параметра:

SQLINTEGER = SQL_NTS;

гс = 1, SQL_CHAR, 50, 0, SQLCHAR = = 2, 50, 0, SQLCHAR SQLINTEGER = SQL_NTS;

3, SQL_C_CHAR, 16, 0, Первый и второй параметры — входные. привязываются с помощью SQL_PARAM_INPUT. Для третьего, выход параметра мы указали Константу Все наши являются текстовыми строками. Локальные перемен ные, которые мы будем к привязывать, расположены в массивах символов типа SQLCHAR. Соответственно через четвертый и пятый мы переда ем функции SQLBindParameter константы SQL_C_CHAR и Обратите внимание, как мы указываем количество символов в параметре (значение функции SQLBindParameter). Входные параметры Глава 6. Связь приложений с данных через ODBC для передачи имени пользователя и пароля, причем соответствующие столбцы в базе данных могут содержать до 50 символов. Выходной параметр предназначен для передачи строк, размером не более 16 символов.

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

Запуск процедуры Как мы уже говорили, для запуска на выполнение хранимых процедур можно воспользоваться уже знакомой Вам функцией Ниже показан фрагмент кода, в котором запускается процедура с тремя па раметрами:

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

{? call Напомним, что при выполнении привязки параметров хранимой процедуры функции SQLBindParameter необходимо номер привязываемого параметра Если хранимая процедура возвращает то для привязки переменной к этому значению необходимо указать номер 1. При этом остальные параметры процедуры нумеруются, начиная со значения 2.

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

Например, если процедура обновляет или записи в базе данных или в зависимости от тех или иных условий возвращает выходные параметры, не из меняя базу набор записей может и создаваться.

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

Если эти результаты не нужны, их можно проигнорировать, вызвав ее в функцию = != •:

!= && break;

Базы данных в Интернете. Практическое руководство После завершения цикла, функция вернет SQL_NO_DATA, программа может получить параметры из локальных к которым эти параметры были привязаны до запуска Программа Применение описанных методик вызова хранимых процедур с параметра ми демонстрируется на примере консольной программы ODBCPARAM.

Программа ODBCPARAM у и запрос к таблице managers базы данных Bookstore и затем права пользователя:

Login name:

Password: rights: Administrator Если пароль или идентификатор указаны прав на кон соли появляется строка Login name: frolov Password: rights: nothing Здесь мы не будем описывать глобальные определения и переменные про граммы ODBCPARAM, так как они аналогичны в программе (см. ранее в этой главе). Вместо этого мы сразу расска жем о все основные действия.

Сразу запуска функция main получает все идентифика торы и открывает соединение с источником Ниже показаны фрагмен ты кода, выполняющие эти операции:

гс = NULL, гс = = hEnv, &hDbc);

= SQLConnect(hDbc, szOSN, Обработка ошибок опущена краткости. выполняется точно таким же образом, как и в программе ODBCAPP.

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

CREATE varchar(50), varchar(50), output AS IF NOT * FROM Глава 6. Связь приложений с базами данных через ODBC INSERT managers Password, Rights, SELECT SELECT FROM WHERE AND UPDATE managers SET WHERE откорректировано значение, возвращаемое в случае отсутствия запи си сотрудника в данных. Вместо пустой строки возвращается стро ка Как видите, процедура имеет два входных и один параметры. Получив управление, она проверяет существование записей в таб managers. Если таблица пуста, в ней создается новая запись с правами адми нистратора. Это нужно для начальной настройки системы при первом запуске.

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

идентификатора команды выполняется, как и функцией гс = Далее вводит с консоли и привязывает к соответствующему па раметру хранимой процедуры ManagerLogin строку содержащую имя сотрудника:

SQLCHAR = name:

= 1, SQL_C_CHAR, SQL_CHAR, 50, 0, szAdminName, 50, образом выполняется ввод пароля и привязка szAdminPass, предназначенной для пароля:

SQLCHAR SQLINTEGER = = 2, SQL_CHAR, 50, 0, szAdminPass, 50, В обоих случаях мы параметры константой 288 Базы данных в Интернете. Практическое руководство Выходной параметр с применением константы SQL_PA SQLINTEGER = 3, 16, 0, 16, К нему массив Именно сюда будет записан результат работы хранимой процедуры Для запуска хранимой процедуры на выполнение мы вызываем SOLExecDirect, передавая ей идентификатор команды и шаблон процедуры ManagerLogin:

гс = (unsigned = != == -1) break;

.

После того как программа убедится в отсутствии наборов записей (что в на шем случае не требуется делать, так как процедура ManagerLogin создает ни каких наборов), она выводит полученные права сотрудника:

rights:

Перед завершением работы освобождает идентификатор команды, отключается от источника данных, а затем освобождает идентификаторы источ ника и среды исполнения;

Расширения CGI и ISAPI сервера Web В главах нашей книги мы познакомили Вас с различными метода ми доступа к базам данных, для использования в приложениях Ин тернета и в Большинство таких приложений, выполняющих доста точно сложные операции, можно построить с технологии ASP.

Однако в некоторых случаях Вам придется создавать собственные расшире ния сервера Web в виде программ CGI и 1SAPI, Как правило, та кие расширения, работающие на том же сервере, что и сервис Web, необходимы для обращения к нестандартным интерфейсам, например к интерфейсам платеж ных систем компаний, кредитных карточек Интернет.

Если компания предоставляет в Ваше распоряжение фейсный модуль в виде объекта компонентной модели Microsoft COM, к нему можно обращаться непосредственно из серверного сценария, расположенного на страницах ASP. чаще всего модуль поставляется в виде библиотеки ди намической загрузки DLL, экспортирующей набор функций. Такие функции легко вызываются из программ, составленных на языке С, но они недоступны программам серверного сценария или Script, в страни цы ASP.

Необходимо отметить, что, если Вы по каким-либо причинам не можете или не желаете применять технологию ASP, Вы вполне обойдетесь и без нее. К Ва шим услугам приложения с базами данных для Интернета или раз с использованием одних только расширений сервера Web. Однако этот путь представляется нам более трудным, так как он предполагает программирование на уровне вызова программного Win32.

К тому же программы расширений намного сложнее в отладке но сравнению с серверными ASP.

В этой главе мы Вам о том, как создать расширения сервера Web, на базе Microsoft Internet Information Server версии 4.0, в виде программ CGI и приложений ISAPI.

Так как наша книга посвящена базам данных, то мы рассмотрим вопросы интеграции приложений CGI и ISAPI с сервером базы Microsoft SQL Server.

290 Базы в Практическое руководство Программы CGI и базы данных Если Вы хотя бы чуть-чуть занимались разработкой приложений для Интерне та, Вы наверняка слышали о программах CGT. Тем не менее мы позволим себе немного рассказать о них.

Что кроется за аббревиатурой CGI — это стандартный шлюзовой интерфейс (Common Gateway для запуска внешних программ под управлением сервера Web.

приложениями CGI называются программы, которые, пользуясь этим интерфей сом, получают через протокол HTTP информацию от удаленного пользователя, ее и возвращают обработки обратно в виде ссылки на уже существующий документ HTML или другой объект (например, графичес кое изображение) или в виде HTML, созданного динамически.

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

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

Кроме того, в этой формах предусматривается которую следует щелкнуть после заполнения всех полей, Когда пользователь заполняет форму и щелкает указанную кнопку, данные приложению CGI, путь к которому задается в заголовке формы. Это получает через HTTP данные из полей формы в виде «имя После обработки полученных данных приложение создает документ HTML и записывает его в стандартное устройство вывода Этот документ затем автоматически передается удаленному пользователю.

Так как приложение CGI представляет собой не что иное, как программу, Вы оттранслировать ее для той операционной системы, под управлением которой работает Ваш сервер Web. В нашем случае необходимо создать консоль ное Win32 путайте его с консольной программой — разные вещи).

Заметим, что программы C.GI, создаваемые для системы Unix, часто составляют с применением интерпретируемого языка Perl. паша книга ориентирована па применение Microsoft, поэтому мы не бу дем касаться этой темы. Заметим только, что для платформы Microsoft Win dows NT также существуют реализации языка Perl.

Немного о формах HTML Чаще всего программы CGI (и ISAPI, которые мы рассмотрим поз же) применяются для введенных посетителями Web при помощи форм. Хотя Вы уже имеете некоторый опыт в создании форм, мы рассмотрим некоторые вопросы, касающиеся взаимодействия форм и расшире ний сервера Web.

7. Расширения CGI и ISAPI сервера Web Как Вы знаете, форма элементы управления, которых пользователь вводит текстовые или цифровые значения, выбирает строки из списков. В форме могут располагаться переключатели, обычные или графичес кие кнопки.

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