Эта глава содержит информацию относительно разработки прикладных программ,
которые используют MyODBC как интерфейс, чтобы обратиться к серверу MySQL.
В общем виде, чтобы работать с сервером MySQL из любой программы через
ODBC/MyODBC, надо сделать следующее:
- Настроить MyODBC DSN
- Подключиться к серверу MySQL
- Провести инициализацию
- Выполнить команды SQL
- Получить результаты
- Обработать транзакции
- Отсоединиться от сервера
Большинство прикладных программ использует некоторое изменение этих шагов.
Источник данных идентифицирует путь для данных, который может включать
сетевую библиотеку, сервер, базу данных и другие атрибуты. В нашем случае
источник данных представляет собой путь к базе данных MySQL
. Чтобы
соединиться с источником данных, Driver Manager проверяет системный реестр
Windows для получения специфической информации подключения.
ODBC Driver Manager
и MyODBC Drivers
использует
вход системного реестра, созданный ODBC Data Source Administrator
.
Этот вход содержит информацию относительно каждого источника данных и связанного
с ним драйвера. Прежде, чем Вы сможете соединяться с источником данных,
информация о подключении должна быть добавлена к системному реестру.
Чтобы добавлять и конфигурировать источники данных, используйте
ODBC Data Source Administrator
. ODBC
Administrator
модифицирует информацию о подключениях к
источникам данных. Поскольку Вы добавляете источники данных, ODBC
Administrator
модифицирует информацию системного реестра для
них.
Чтобы открыть ODBC Administrator
из
Control Panel:
- Нажмите
Start
, укажите на
Settings
и щелкните Control Panel
.
- На системах под Microsoft Windows 2000 дважды щелкните по
Administrative Tools
, а затем дважды щелкните по
Data Sources (ODBC)
. На компьютерах под
предыдущими версиями Microsoft Windows дважды щелкните по 32-bit
ODBC
или по ODBC
.
Чтобы добавить источник данных в Windows:
- Откройте
ODBC Data Source Administrator
.
- В диалоговом окне
ODBC Data Source Administrator
нажмите Add
. Откроется диалоговое окно
Create New Data Source
.
- Выберите там
MySQL ODBC 3.51 Driver
и
нажмите на Finish
. Появится диалоговое окно
MySQL ODBC 3.51 Driver - DSN Configuration
.
- В окне
Data Source Name
впечатайте имя
источника данных, к которому Вы хотите обращаться. Это может быть любое
имеющее силу имя, которое понравилось.
- В окне
Description
введите описание
необходимое для DSN.
- В окне
Host or Server Name (or IP)
напечатайте имя сервера MySQL, к которому Вы хотите обращаться. По умолчанию
это local host.
- В окне
Database Name
укажите имя MySQL базы
данных, которая будет применяться как заданная по умолчанию база данных.
- В окне
User
задайте имя пользователя базы
данных (user ID).
- В окне
Password
надо задать пароль.
- В окне
Port
напечатайте номер порта, если
это не значение по умолчанию 3306.
- В окне
SQL Command
Вы можете вводить
факультативную команду SQL, которую серверу надлежит выполнить сразу после
установления подключения.
Теперь нажмите OK
, чтобы добавить этот источник
данных. Обратите внимание:
при щелчке на OK
диалоговое окно Data Sources dialog, и ODBC Administrator
модифицирует информацию системного реестра. Имя пользователя и
строка подключения станут заданными по умолчанию значениями подключения для
этого источника данных. Вы можете также проверить, достаточны ли Ваши параметры
настройки, чтобы соединиться с сервером, используя кнопку Test
Data Source
. Эта возможность появилась только начиная с
MyODBC 3.51
.
Driver Options: Вы можете также видеть кнопку
Options
, которая отобразит диалог дополнительных
параметров, которые управляют поведением драйвера.
Обратите внимание, что параметры Driver Trace
Options
будут заблокированы (нарисованы серым цветом) при использовании
обычной версии DLL.
Чтобы изменить источник данных в Windows:
- Откройте окно
ODBC Data Source Administrator
. Выберите соответствующую вкладку DSN.
- Выберите источник данных MySQL, который Вы хотите изменить, а затем
нажмите
modify
и щелкните по
Configure
. Откроется диалоговое окно
MySQL ODBC 3.51 Driver - DSN Configuration
.
- Измените соответствующие поля источника данных, а затем нажмите
OK
.
Когда Вы закончите изменять информацию в этом диалоговом окне,
ODBC Administrator
модифицирует информацию
системного реестра.
Чтобы настроить источник данных в Unix:
В Unix
Вы можете конфигурировать DSN-входы
непосредственно в файле ODBC.INI. Имеется пример файла odbc.ini с myodbc как
DSN-имя для MyODBC 2.50 и myodbc3 для MyODBC 3.51 Drivers:
;
; odbc.ini configuration for MyODBC and MyODBC 3.51 Drivers
;
[ODBC Data Sources]
myodbc = MySQL ODBC 2.50 Driver DSN
myodbc3 = MySQL ODBC 3.51 Driver DSNа
[myodbc]
Driver = /usr/local/lib/libmyodbc.so
Description = MySQL ODBC 2.50 Driver DSN
SERVER = localhost
PORT =
USER = root
Password =
Database = test
OPTION = 3
SOCKET =
[myodbc3]
Driver = /usr/local/lib/libmyodbc3.so
Description = MySQL ODBC 3.51 Driver DSN
SERVER = localhost
PORT =
USER = root
Password =
Database = test
OPTION = 3
SOCKET =
[Default]
Driver = /usr/local/lib/libmyodbc3.so
Description = MySQL ODBC 3.51 Driver DSN
SERVER = localhost
PORT =
USER = root
Password =
Database = test
OPTION = 3
SOCKET =
Обратите внимание: если Вы используете unixODBC, то Вы
можете использовать следующие инструментальные средства чтобы настроить DSN:
Можно определять следующие параметры для MyODBC или для
MyODBC 3.51 в секции [Data Source Name]
файла
ODBC.INI
или через параметр InConnectionString
в
вызове SQLDriverConnect()
.
Параметр |
Значение по умолчанию |
Комментарий |
user |
ODBC (в Windows) |
Имя пользователя для связи с MySQL. |
server |
localhost |
Имя сервера MySQL. |
database |
|
База данных по умолчанию |
option |
0 |
Целое число, которым Вы можете определять как должен работать
MyODBC 3.51. Описано чуть ниже. |
port |
3306 |
Порт TCP/IP, чтобы использовать, если server не равен
localhost . |
stmt |
|
Инструкция, которая будет выполнена, когда установлено подключение к
MySQL . |
password |
|
Пароль для комбинации server user . |
socket |
|
Сокет или именованный канал Windows для связи. |
Параметр OPTION
используется, чтобы сообщить MyODBC
3.51, что пользователь не на 100% совместим с ODBC. Следующие параметры
перечислены в том же самом порядке, в каком они появляются в MyODBC
3.51:
Бит |
Описание |
1 |
Пользователь не может обрабатывать ситуацию, когда
MyODBC возвращает реальную ширину столбца. |
2 |
Пользователь не может обрабатывать ситуацию, когда MySQL возвращает
истинное число обработанных строк. Если этот параметр установлен, MySQL
вернет число найденных строк. Нужно иметь MySQL 3.21.14 или более новый,
чтобы это работало. |
4 |
Создать протокол трассировки в файле c:\myodbc.log
(/tmp/myodbc.log). Это аналогично указанию
MYSQL_DEBUG=d:t:O,c::\myodbc.log в
AUTOEXEC.BAT. |
8 |
Не устанавливать ограничений пакета для результатов и
параметров. |
16 |
-Не запрашивать ничего, даже если драйвер хочет запросить. |
32 |
Включить или отключить поддержку динамического курсора. Это не
работает в MyODBC 2.50. |
64 |
Игнорировать использование имени базы данных в формате
database.table.column. |
128 |
Использование экспериментальных курсоров ODBC manager. |
256 |
Отключить использование расширенной (экспериментальной) выборки. |
512 |
Дополнить поля типа CHAR до полной длины столбца. |
1024 |
SQLDescribeCol() возвратит полностью квалифицированные имена
столбцов. |
2048 |
Использовать сжатый протокол клиент-сервер. |
4096 |
Сервер должен игнорировать пробел между именем функции и
'(' (нужно для Power Builder). Это делает все ключевые слова
именами функций! |
8192 |
Соединиться через именованный канал с сервером mysqld под
NT. |
16384 |
Менять столбцы типа LONGLONG на столбцы INT (некоторые прикладные
программы не могут корректно обрабатывать LONGLONG). |
32768 |
Вернуть user как Table_qualifier и Table_owner из SQLTables. |
65536 |
Читать параметры из групп client и odbc в
файле my.cnf |
131072 |
Добавить некоторые дополнительные проверки безопасности (вроде бы не
очень и надо, но...). |
262144 |
Выключить использование транзакций |
524288 |
Включить регистрацию запросов в файле c:\myodbc.sql
(/tmp/myodbc.sql). Доступно только в режиме отладки в специальной
версии драйвера. |
Если Вы хотите иметь много параметров, Вы должны сложить вышеупомянутые
числа. Например, установка опции в 12 (4+8) дает Вам отладку без ограничений на
размеры пакета.
По умолчанию MYODBC3.DLL компилируется для оптимальной
эффективности. Если Вы хотите отладить MyODBC 3.51
(например, чтобы
получить трассировку), используйте MYODBCD3.DLL
вместо стандартного
файла MYODBC3.DLL
.
Прикладная программа может быть связана с любом числом источников данных и
драйверов. Они могут быть вариантами того же самого драйвера и ряда источников
данных или несколькими подключениями с тем же самым драйвером и источником
данных. Прикладная программа должна сделать следующее, чтобы соединиться с
сервером MySQL через MyODBC:
Распределите дескриптор среды
Установите версию ODBC
Распределите дескриптор подключения
Установите факультативные атрибуты подключения перед подключением
Создайте подключение к серверу
Установите факультативные атрибуты подключения после подключением
Прежде, чем прикладная программа сможет использовать любую функцию ODBC, надо
инициализировать ODBC-связь с помощью интерфейса и сопоставить с ней дескриптор
среды. Он обеспечивает доступ к глобальной информации типа имеющих силу
дескрипторов подключения и активных дескрипторов подключения.
Чтобы распределить правильный дескриптор среды, прикладная программа:
- Объявляет переменную типа SQLHENV. Например, прикладная программа могла бы
использовать объявление:
SQLHENV henv;
- Вызывает SQLAllocHandle (в MyODBC 2.50 называется SQLAllocEnv) и передает
адрес этой переменной и опции SQL_HANDLE_ENV как:
SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv) или
SQLAllocEnv(&henv)
Если прикладная программа связана через Driver Manager, то это обращение
загружает Driver Manager. Он не вызывает SQLAllocHandle
в драйвере
потому, что пока не знает, который драйвер вызвать. Это откладывает вызов
SQLAllocHandle
в драйвере до получения вызовов из прикладной
программы, чтобы соединиться с источником данных: тогда-то будет однозначно
ясно, какой драйвер нужен.
Если прикладная программа связана непосредственно с драйвером, то это
обращение загружает драйвер, и уже драйвер формирует информацию среды и
возвращает распределенную структуру обратно прикладной программе.
Если Вы используете драйвер MyODBC 2.50, то Вы можете игнорировать этот
раздел. Прежде, чем прикладная программа создаст соединение, необходимо
установить атрибут SQL_ATTR_ODBC_VERSION среды, используя SQLSetEnvAttr:
SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER) SQL_OV_ODBC3, 0);
Этот атрибут заявляет, что прикладная программа следует спецификациям ODBC
2.x или ODBC 3.x при использовании следующих элементов:
- SQLSTATE: Много значений SQLSTATE различны в ODBC 2.x и ODBC 3.x. Для
получения списка кодов SQLSTATE, возвращаемых драйвером MyODBC 3.51 обратитесь
к разделу "
Коды ошибок MyODBC".
- Типы Date, Time и Timestamp: следующая таблица показывает идентификаторы
типов для данных date, time и timestamp в ODBC 2.x и в ODBC 3.x.
ODBC 2.X |
ODBC 3.X |
Идентификаторы типов в SQL |
SQL_DATE |
SQL_TYPE_DATE |
SQL_TIME |
SQL_TYPE_TIME |
SQL_TIMESTAMP |
SQL_TYPE_TIMESTAMP |
Идентификаторы типов в C |
SQL_C_DATE |
SQL_C_TYPE_DATE |
SQL_C_TIME |
SQL_C_TYPE_TIME |
SQL_C_TIMESTAMP |
SQL_C_TYPE_TIMESTAMP |
MyODBC 3.51 контролирует версию спецификации ODBC, для которой прикладная
программа написана и отвечает соответственно. Например, если прикладная
программа следует версии ODBC 2.x и вызывает SQLExecute до вызова SQLPrepare,
драйвер вернет: SQLSTATE S1010 (Function sequence error). Если
прикладная программа поддерживает спецификацию ODBC 3.x, то это возвращает:
SQLSTATE HY010 (Function sequence error).
Дескриптор подключения обеспечивает доступ к информации относительно того,
является ли подключение открытым или нет, имеют ли силу операторные и
дескрипторные маркеры на подключении, и открыта ли сейчас транзакция.
Прежде, чем прикладная программа сможет соединиться с сервером MySQL или с
драйвером, она должна распределить дескриптор подключения, следующим образом:
Если прикладная программа связана через Driver Manager, то Driver Manager
распределяет память, чтобы сохранить информацию относительно подключения и
возвращает дескриптор подключения прикладной программе. С другой стороны, если
Вы непосредственно компонуете программу через библиотеку драйверов вместо Driver
Manager, то эту работу делает уже драйвер.
Атрибуты подключения представляют собой характеристики подключения. Например,
они определяют, что транзакции происходят в уровне подключения, а уровень
изоляции транзакции представляет собой атрибут подключения. Точно так же время
ожидания входа в систему или число секунд, которые надо ждать при попытке
соединиться перед тайм-аутом, тоже атрибуты подключения.
Атрибуты подключения установлены с помощью SQLSetConnectAttr, а их текущие
параметры настройки могут быть получены с помощью SQLGetConnectAttr. Для
прикладных программ драйвера MyODBC 2.50 Вы можете использовать
SQLSetConnectOption и SQLGetConnectOption.
Атрибуты подключения могут быть установлены до или после подключения, в
зависимости от типа атрибута. Время ожидания входа в систему
SQL_ATTR_LOGIN_TIMEOUT применяется только при установлении связи и важно, только
если установлено перед соединением.
Атрибуты, которые определяют, использовать ли библиотеку курсоров ODBC
(SQL_ATTR_ODBC_CURSORS) и сетевой размер пакета (SQL_ATTR_PACKET_SIZE), должны
быть установлены прежде, чем соединение создано потому что, библиотека курсоров
ODBC находится между Driver Manager и драйвером, а следовательно должно быть
загружена перед драйвером. Подробный перечень атрибутов подключения,
поддерживаемых драйверами MyODBC, есть в разделе "4.5.1
SQLSetConnectAttr".
После распределения среды и дескрипторов подключения и установки
факультативных атрибутов подключения, прикладная программа готова соединиться с
сервером MySQL или драйвером MyODBC (через Driver Manager). Имеются две
различных функции для этого:
- SQLConnect и
- SQLDriverConnect
3.4.5.1 Соединение через SQLConnect
SQLConnect самая простая функция подключения. Требует имя
источника данных и принимает факультативные user ID и пароль. Прикладная
программа передает следующую информацию драйверу через SQLConnect:
DSN:
имя источника данных.
UID:
имя пользователя
для связи с сервером (опционально).
PWD:
соответствующий пароль
(опционально).
Обратите внимание, что, если Вы уже определили имя пользователя и пароль в
параметрах DSN или непосредственно в файле ODBC.INI, Вы можете только определить
имеющий силу DSN, а драйвер внутренне получает другую требуемую информацию из
записей в DSN сам.
Когда из прикладной программы вызван SQLConnect, Driver Manager использует
имя источника данных, чтобы прочитать имя драйвера DLL из соответствующего
раздела файла ODBC.INI или из системного реестра. Это затем загружает драйвер
DLL и передает ему параметры SQLConnect. Если драйвер нуждается в дополнительной
информации, чтобы соединиться с источником данных, он читает эту информацию из
того же самого раздела файла ODBC.INI.
Если прикладная программа определяет имя источника данных, которое не
значится в файле ODBC.INI или в системном реестре, или если прикладная программа
не определяет имя источника данных, Driver Manager ищет заданную по умолчанию
спецификацию источника данных. Если он находит заданный по умолчанию источник
данных, то загружает заданный по умолчанию драйвер и передает ему определенное
прикладная программой имя источника данных. Если не имеется никакого заданного
по умолчанию источника данных, Driver Manager возвращает соответствующую
ошибку.
Пример: следующий пример распределяет необходимую среду,
дескриптор подключения и соединяется с сервером MySQL, используя DSN myodbc3.
SQLHENV henv;
SQLHDBC hdbc;
SQLHSTMT hstmt;
SQLRETURN retcode;
/* Allocate environment handle */
retcode = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv);
if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO)
{
/* Set the ODBC version environment attribute to version 3 */
retcode = SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION,
(SQLPOINTER)SQL_OV_ODBC3, 0);
if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO)
{
/* Allocate connection handle */
retcode = SQLAllocHandle(SQL_HANDLE_DBC, henv, &hdbc);
if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO)
{
/* Connect to data source myodbc3 */
retcode = SQLConnect(hdbc, (SQLCHAR*) "myodbc3", SQL_NTS,
(SQLCHAR*) "myuser", SQL_NTS,
(SQLCHAR*) "mypassword", SQL_NTS);
if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO)
{
/* Set auto commit to ON */
retcode = SQLSetConnectAttr(hdbc, SQL_ATTR_AUTO_COMMIT,
SQL_AUTOCOMMIT_ON,0);
printf("\n autocommit returned :%d", redcode);
/* Allocate statement handle */
retcode = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt);
if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO)
{
/* Process data */
;
;
;
/* Free stattemt handle */
SQLFreeHandle(SQL_HANDLE_STMT, hstmt);
}
/* Disconnect from the server */
SQLDisconnect(hdbc);
}
/* Close the connection handle */
SQLFreeHandle(SQL_HANDLE_DBC, hdbc);
}
}
/* Close the environment handle */
SQLFreeHandle(SQL_HANDLE_ENV, henv);
3.4.5.2 Связь через SQLDriverConnect
SQLDriverConnect используется, чтобы соединиться с сервером,
используя строку подключения. Можно использовать SQLDriverConnect вместо
SQLConnect по следующим причинам:
- Позволить прикладной программе использовать специфическую для драйвера
информацию подключения.
- Чтобы драйвер запрашивал пользователя относительно информации подключения.
- Соединяться без определения источника данных (DSN less
connection).
Строка подключения может состоять из одного или большего количества
параметров MyODBC подключения, отделяемых точкой с запятой (;). Если драйвер
должен запрашивать пользователя относительно информации подключения, то он
отображает диалог подключения.
3.4.5.3 Строка подключения для SQLDriverConnect
Используя myodbc3 как MySQL ODBC 3.51 DSN:
ConnectionString = "DSN=myodbc3"
DSN Less Connection:
ConnectionString = "DRIVER={MySQL ODBC 3.51 Driver}; SERVER=localhost;\
DATABASE=test; USER=monty; PASSWORD=monty;\
OPTION=4;"
Как только подключение установлено, прикладная программа должна получить
большее количество информации относительно драйвера и источника данных, с
которым он связан. Использование следующего API поможет это устроить:
SQLGetInfo
: возвращает общую информацию относительно драйвера
и источника данных, связанного с подключением. Например, какие инструкции SQL
прикладная программа выполнит? Прикладная программа использует скроллируемые
курсоры? Транзакции? Процедуры? Длинные данные?
SQLGetTypeInfo:
возвращает информацию относительно типов
данных, поддерживаемых сервером. Драйвер возвращает информацию в форме набора
результатов SQL. Типы данных предназначены для использования в инструкциях
Data Definition Language (DDL).
SQLGetFunctions:
возвращает информацию относительно того,
поддерживает ли драйвер специфическую функцию ODBC. Прикладная программа может
всегда использовать эту функцию, чтобы проверить, поддерживает ли драйвер
некий API или нет.
Пример: получает имя драйвера и версию, имя и версию
сервера и соглашения SQL, поддерживаемые драйвером.
SQLHDBC hdbc;
SQLRETURN retcode;
SQLCHAR strValue[50];
SQLINTEGER nValue;
SQLSMALLINT pcbValue;
/* Connect to the server */
retcode = SQLConnect (..)
if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO)
{
/* get the driver name */
retcode = SQLGetInfo(hdbc, SQL_DRIVER_NAME,
strValue, 50, &pcbValue);
if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO)
{
printf("driver name:%s",strValue);
}
/* get the driver version */
retcode = SQLGetInfo(hdbc, SQL_DRIVER_VER,
strValue, 50, &pcbValue);
if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO)
{
printf("driver version:%s",strValue);
}
/* get the server name */
retcode = SQLGetInfo(hdbc, SQL_DBMS_NAME,
strValue, 50, &pcbValue);
if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO)
{
printf("server name:%s",strValue);
}
/* get the SQL conformance*/
retcode = SQLGetInfo(hdbc, SQL_SQL_CONFORMANCE,
&nValue, 0, &pcbValue);
if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO)
{
printf("SQL Conformance:%d",nValue);
}
}
Когда прикладная программа закончила использовать сервер MySQL, она должна
в обязательном порядке закрыть подключение и освободить все предварительно
распределенные дескрипторы. Чтобы завершать подключение из MyODBC нужно:
- Вызвать
SQLDisconnect
, чтобы закрыть подключение. Если
имеются любые открытые операторные дескрипторы на этом подключении, то
драйвер внутренне освобождает все открытые инструкции для этого подключения.
Прикладная программа может затем использовать дескриптор подключения, чтобы
повторно соединиться с тем же самым источником данных или присоединиться к
другому источнику данных, если дескриптор подключения не был освобожден.
- Вызвать
SQLFreeHandle
с опцией SQL_HANDLE_DBC, чтобы
освободить подключение и все ресурсы, связанные с дескриптором.
- Вызвать
SQLFreeHandle
с опцией SQL_HANDLE_ENV, чтобы
освободить среду и все ресурсы, связанные с дескриптором.
Обратите внимание, если Вы используете драйвер MyODBC 2.50, Вы должны
использовать SQLFreeConnect и SQLFreeEnv, чтобы освободить дескрипторы
подключения и среды соответственно.
Ну ладно, подключение установлено, а дальше-то что? Надо работать с
сервером, для этого все и затевалось. Работа эта происходит на базе обмена
командами SQL и их результатами. Вот это самое сложное. Прикладная программа
может представлять на рассмотрение любую инструкцию SQL, поддерживаемую
сервером MySQL. ODBC-программы выполняют почти весь доступ к базе данных,
выполняя инструкции SQL. Общая последовательность событий:
- Распределите операторный дескриптор
- Установите факультативные операторные атрибуты,
- Выполните инструкцию,
- Соберите все результаты и наконец
- Освободите операторный дескриптор.
Операторный дескриптор обеспечивает доступ к операторной информации, типа
сообщений об ошибках, имени курсора и информации состояния для обработки
инструкции SQL. Прежде, чем прикладная программа сможет представлять на
рассмотрение серверу инструкцию SQL, она должна распределить операторный
дескриптор, используя SQLAllocHandle (или SQLAllocStmt в MyODBC 2.50):
Драйвер идентифицирует, которую инструкцию надо использовать при вызове
функций ODBC через дескриптор инструкции.
3.5.2 Установка операторных
атрибутов
Операторные атрибуты представляют собой характеристики инструкции.
Например, они используются, чтобы установить имя курсора для специфической
инструкции или задать максимальное количество строк, которые будут выбраны в
одной инструкции выборки.
Операторные атрибуты могут быть установлены с помощью SQLSetStmtAttr, а их
актуальные параметры настройки можно узнать через вызов SQLGetStmtAttr
(SQLSetStmtOption и SQLGetConnectOption соответственно для MyODBC 2.50).
Поскольку решительно все операторные атрибуты имеют значения по умолчанию,
прикладная программа не обязана их менять, можно оставить все как есть.
MyODBC позволяет прикладной программе представлять на рассмотрение
инструкции SQL двумя различными способами:
- Подготовленное выполнение
- Прямое выполнение
Подготовленное выполнение представляет собой эффективный способ выполнить
инструкцию больше одного раза. Инструкция сначала компилируется в план
доступа. План доступа затем будет выполнен столько раз, сколько понадобится.
Подготовленное выполнение более предпочтительно, если прикладная программа:
- Выполняет инструкцию больше одного раза, меняя значения параметра.
- Нуждается в информации относительно инструкции SQL или набора
результатов до выполнения.
Подготовленное выполнение главным образом достигнуто через MyODBC API
SQLPrepare и SQLExecute. Подготовленная инструкция выполняется быстрее, чем
неприготовленная инструкция или прямое выполнение потому, что драйвер
компилирует инструкцию, строит для нее план доступа и возвращает идентификатор
плана доступа обратно прикладной программе. Драйвер минимизирует затраты
времени на обработку инструкции, поскольку он не должен каждый раз строить
план доступа. Уменьшается и трафик.
Чтобы подготовить и выполнить инструкцию, прикладная программа:
- Вызывает SQLPrepare и передает строку, содержащую инструкцию SQL.
- Устанавливает значения любых операторных параметров.
- Вызывает SQLExecute и делает любую дополнительную обработку, которая
является необходимой, типа выборки данных.
- По мере надобности повторяет 2 и 3 шаги.
- Когда вызвана SQLPrepare, драйвер изменяет инструкцию SQL, чтобы
использовать синтаксис MySQL без того, чтобы анализировать инструкцию. Это
включает замену управляющих последовательностей. Но драйвер не возвращает
никаких синтаксических и семантических ошибок.
- При вызове SQLExecute драйвер:
- Получает текущий параметр, оценивает и преобразует его по мере
необходимости.
- Посылает идентификатор плана доступа и преобразованные значения
параметров на сервер MySQL.
- Возвращает любые ошибки. Это ошибки, возникшие во время выполнения
программы, типа SQLSTATE 24000 (Invalid cursor state), а также
синтаксические и семантические ошибки, если они есть.
Пример: этот пример объясняет, как прикладная программа
может использовать подготовленное выполнение. Выборка готовит инструкцию
INSERT и вставляет 100 строк данных, заменяя буферные значения.
SQLHSTMT hstmt;
SQLRETURN retcode;
retcode = SQLPrepare(hstmt, "INSERT INTO EMP(ID,NAME) VALUES(?,?)",
SQL_NTS);
if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO)
{
SQLINTEGER id;
SQLCHAR name[30];
/* do the binding for parameter 1, id */
retcode = SQLBindParameter(hstmt,1,SQL_PARAM_INPUT, SQL_C_LONG,
SQL_INTEGER, 0,0, &id, 0, NULL);
if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO)
{
/* Now do the bindings for parameter 2, name */
retcode = SQLBindParameter(hstmt,1,SQL_PARAM_INPUT, SQL_C_CHAR,
SQL_VARCHAR, 0,0, name,
sizeof(name),NULL);
if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO)
{
/* Now insert data by changing id and name buffer values */
for (id=1; id <= 100; id++)
{
/* Set name as Сmysql1Т, Сmysql2ТЕ */
sprintf(name,Фmysql%dФ,id);
retcode = SQLExecute(hstmt);
}
}
}
/* Free param buffer resources */
retcode = SQLFreeStmt(hstmt, SQL_REST_PARAMS);
}
Прямое выполнение представляет собой самый простой способ выполнить
инструкцию. Прямое выполнение обычно используется универсальными прикладными
программами, которые формируют и выполняют инструкции во время выполнения.
Например, следующий код формирует инструкцию SQL и выполняет ее один раз:
SQLCHAR *statement;
// Build an SQL statement.
printf("enter the SQL statement:");
scanf("%s",&statement);
// Execute the statement.
SQLExecDirect (hstmt, statement, SQL_NTS);
Прикладная программа должна выполнить инструкции, используя именно прямое
выполнение, если:
- Инструкция нужна однократно.
- Прикладная программа не нуждается в информации относительно набора
результатов до выполнения.
Основной недостаток использования прямого выполнения: инструкция SQL
анализируется каждый раз, когда выполняется.
Чтобы выполнить инструкцию непосредственно, прикладная программа
выполняет следующий набор действий:
- Устанавливает значения любых параметров.
- Вызывает SQLExecDirect и передает строку, содержащую инструкцию SQL.
- При вызове SQLExecDirect драйвер:
- Изменяет инструкцию SQL, чтобы использовать синтаксис MySQL без того,
чтобы анализировать инструкцию. Это включает замену всеъ управляющих
последовательностей языка.
- Получает актуальный параметр, оценивает его и изменяет инструкцию SQL,
меняя маркеры параметра на данные с соответствующими преобразованиями.
- Посылает измененную инструкцию SQL MySQL для выполнения.
- Возвращает любые ошибки. Они включают диагностику выполнения,
например, SQLSTATE 24000 (Invalid cursor state), синтаксические ошибки,
типа SQLSTATE 42000 (Syntax error or access violation) и семантические
ошибки, вроде SQLSTATE 42S02 (Base table or view not
found).
Пример:
этот пример объясняет, как прикладная программа
может использовать прямое выполнение. Он создает таблицу, вставляет,
модифицирует и удаляет некоторые строки данных, а в заключение удаляет всю
таблицу.
SQLHSTMT hstmt;
SQLRETURN retcode;
/* create table as "my_test" with integer and text field */
retcode = SQLExecDirect(hstmt, "CREATE TABLE my_test(id int,
name text", SQL_NTS);
if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO)
{
printf("table created successfully..");
/* insert 2 rows of data to the table Сmy_testТ */
retcode = SQLExecDirect(hstmt,
"INSERT INTO my_test VALUES(10,'mysql')",
SQL_NTS);
if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO)
{
printf("row 1 inserted successfully..");
}
retcode = SQLExecDirect(hstmt,
"INSERT INTO my_test VALUES(20,'monty')",
SQL_NTS);
if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO)
{
printf("row 2 inserted successfully..");
}
/* Now update the second row by changing id from 20 to 100 */
retcode = SQLExecDirect(hstmt, "UPDATE my_test SET id=100
WHERE name='monty', SQL_NTS);
if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO)
{
SQLINTEGER rowcount;
printf("row updated successfully..");
/* Get total number of rows affected by the update statement*/
retcode=SQLRowCount(hstmt, &rowcount);
printf("total rows affected by the updated statement:%d",
rowcount);
}
/* Now delete the newly updated row */
retcode = SQLExecDirect(hstmt, "DELETE FROM my_test WHERE id=100",
SQL_NTS);
if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO)
{
SQLINTEGER rowcount;
printf("row deleted successfully..");
/* Get total number of rows affected by the delete statement*/
retcode=SQLRowCount(hstmt, &rowcount);
printf("total rows affected by the delete statement:%d",
rowcount);
}
}
/* now drop the table Сmy_testТ */
retcode = SQLExecDirect(hstmt,"DROP TABLE my_test", SQL_NTS);
if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO)
{
printf(Уtable dropped successfully);
}
Параметром является переменная в инструкции SQL. Инструкция SQL может
содержать маркеры параметров ("?"), которые указывают
значения, которые драйвер получает из прикладной программы во время
выполнения.
Например, прикладная программа могла бы использовать следующую инструкцию,
чтобы вставить строку данных в таблицу EMPLOYEE:
INSERT INTO EMPLOYEE (NAME.AGE) VALUES (?,?)
Прикладная программа может использовать маркеры параметров вместо
литеральных или постоянных значений в инструкции SQL по следующим причинам:
- Требуется выполнить ту же самую подготовленную инструкцию несколько раз
с различными значениями параметра.
- Значения параметра неизвестны, когда инструкция готовится.
- Значения параметра должны быть явно преобразованы из одного типа данных
в другой.
Чтобы устанавливать значение параметра, прикладная программа просто
устанавливает значение переменной, привязанной к этому параметру, используя
SQLBindParameter. Неважно, когда это значение установлено, пока это сделано
прежде, чем инструкция выполнена. Прикладная программа может устанавливать
значение в любое время и менять его столько раз, сколько потребуется.
Когда инструкция выполнена, драйвер просто получает актуальное значение
переменной. Это особенно полезно, когда подготовленная инструкция выполнена
больше, чем однажды: прикладная программа устанавливает новые значения для
некоторых или всех переменных, каждый раз, когда инструкция выполнена.
Если буфер длин использован в вызове SQLBindParameter, он должен быть
установлен в одно из следующих значений прежде, чем инструкция выполнена:
- Длина данных в байтах в связанной переменной. Драйвер проверяет эту
длину только, если переменная символьная или двоичная (ValueType равен
SQL_C_CHAR или SQL_C_BINARY).
- SQL_NTS. Данные являются строкой с нулевым символом в конце.
- SQL_NULL_DATA. Значение данных равно NULL, и драйвер игнорирует значение
связанной переменной.
- SQL_DATA_AT_EXEC или результат макрокоманды SQL_LEN_DATA_AT_EXEC.
Значение параметра должно быть послано с SQLPutData.
Расположения параметров, заданные через SQLBindParameter, останутся
привязанными к маркерам параметра до вызова SQLFreeStmt из прикладной
программы с опцией SQL_RESET_PARAMS или SQL_DROP. Прикладная программа может
связать новое место в памяти с маркером параметра в любое время, вызывая
SQLBindParameter. Пример:
SQLUINTEGER id;
SQLINTEGER idInd;
// Prepare a statement to insert id
SQLPrepare(hstmt, "INSERT INTO my_table VALUES(?)", SQL_NTS);
// Bind id to the parameter for the id column
SQLBindParameter(hstmt, 1, SQL_PARAM_INPUT, SQL_C_ULONG,
SQL_LONG, 0, 0, &id, 0, &idInd);
// Repeatedly execute the statement, to insert 100 rows of data
for (id=1; id <= 100; id++)
{
SQLExecute(hstmt);
}
MySQL определяет данные long как любые символьные или двоичные данные,
превышающие некий размер, обычно 254 символа. Не всегда реально сохранить в
памяти целиком элемент длинных данных. Пример: здоровенный текстовый документ
(например, эта книга в типографском формате PostScript) или растровая
картинка. А поскольку такие данные не могут быть сохранены в одиночном буфере,
прикладная программа посылает их драйверу по частям через SQLPutData, когда
инструкция выполнена.
Обратите внимание, что прикладная программа может фактически посылать любой
тип данных во времени выполнения с помощью SQLPutData, хотя только символьные
и двоичные данные могут быть представлены частями. Однако, если данные
достаточно маленькие, чтобы разместиться в одиночном буфере, не имеется вообще
никакой причины использовать SQLPutData. Намного проще позволять драйверу
получать данные из буфера напрямую.
Когда Вы должны ввести большие количества данных в столбец long varchar или
в long varbinary, Вы можете использовать ODBC-функции SQLPutData и
SQLParamData, чтобы ввести данные в меньших сегментах. Данные обеспечены в
сегментах через SQLPutData, а SQLParamData используется, чтобы проверить
требуют ли параметры данных.
Чтобы посылать длинные данные во время выполнения в сегментах,
прикладная программа выполняет следующие действия:
Готовит SQL-инструкцию
с маркерами параметра там, где будут
данные long или blob. Используется SQLPrepare.
Устанавливает параметр pcbValue
в функции SQLBindParameter
в значение SQL_DATA_AT_EXEC или SQL_LEN_DATA_AT_EXEC. Это позволяет драйверу
узнать, что Вы будете обеспечивать значения для этого параметра во время
выполнения, используя SQLPutData.
Выполняет команду SQL
. Если инструкция уже подготовлена,
выполняется подготовленная инструкция, используя SQLExecute или
SQLExecDirect. Если имеются любые параметры, которые должны получить данные
во времени выполнения, то драйвер возвращает SQL_NEED_DATA.
Вызывает SQLParamData
в ответ на возврат значения
SQL_NEED_DATA. Если длинные данные должны быть посланы, SQLParamData вернет
SQL_NEED_DATA. В буфере, указанном параметром ValuePtrPtr, драйвер
возвращает значение, которое идентифицирует параметр ожидания данных при
выполнении. Если имеется больше, чем один такой параметр, прикладная
программа должна использовать это значение, чтобы определить, который
параметр ожидается. Заметьте, что данные могут быть запрошены драйвером в
любом порядке.
Вызывает SQLPutData:
, чтобы послать данные параметра
драйверу. Если данные параметра не вписываются в одиночный буфер, что часто
имеет место с длинными данными, вызовы SQLPutData из прикладной программы
будут повторяться для передачи последующих порций данных.
Вызывает SQLParamData:
если код возврата равен
SQL_NEED_DATA, следующий параметр, который ожидает данные во время
выполнения, готов их получить, и Вы должны вернуться к шагу 4. Если код
возврата равен SQL_SUCCESS или хотя бы SQL_SUCCESS_WITH_INFO, все данные для
всех параметров, ожидающих данных во время выполнения, посланы, и инструкция
SQL завершила выполнение.
Перед выполнением новой инструкции SQL, прикладная программа должна
убедиться, что текущие операторные параметры настройки соответствующие. Они
включают операторные атрибуты, связанные параметры и наборы результатов.
Вообще, параметры и наборы результатов для старой инструкции SQL должны быть
освобождены (вызовом SQLFreeStmt с опцией SQL_RESET_PARAMS или SQL_UNBIND).
Когда прикладная программа закончила использовать инструкцию, она вызывает
SQLFreeHandle с опцией SQL_HANDLE_STMT или SQLFreeStmt с опцией SQL_DROP,
чтобы освободить инструкцию. Вызов SQLDisconnect автоматически освобождает все
инструкции для данного подключения.
Функция SQLFreeStmt имеет четыре опции:
Опция |
Что она делает |
SQL_CLOSE |
Закрывает курсор, если он существует, и отбрасывает ждущие обработки
результаты. Прикладная программа может использовать операторный
дескриптор позже. |
SQL_DROP |
Закрывает курсор, если он существует, отбрасывает ждущие обработки
результаты и освобождает все ресурсы, связанные с операторным
дескриптором. |
SQL_UNBIND |
Освобождает все буфера возвратов, связанные SQLBindCol с операторным
дескриптором. |
SQL_RESET_PARAMS |
Освобождает все буфера параметров, запрошенные SQLBindParameter для
операторного дескриптора. |
Набор результатов представляет собой набор строк, который соответствует
некоторым критериям. Когда прикладная программа должна получить данные из базы
данных, наиболее общий метод состоит в том, чтобы выполнить запрос, используя
инструкции SELECT или SHOW.
В большинстве случаев, когда прикладная программа не уверена, относительно
того, вернула ли специфическая инструкция набор результатов, она должна
вызвать SQLNumResultCols, чтобы определить число столбцов в наборе
результатов. Если это 0, инструкция не создала набор результатов.
Прикладная программа может вызывать SQLNumResultCols в любой момент после
того, как инструкция подготовлена или выполнена. Обратите внимание, что если
Вы вызываете SQLNumResultCols на подготовленной, но не выполненной инструкции,
прикладная программа теряет в эффективности, поскольку драйвер внутренне
выполняет подготовленную инструкцию, чтобы вернуть информацию обратно
прикладной программе.
ОБРАТИТЕ ВНИМАНИЕ, для инструкций типа INSERT,
UPDATE или DELETE вызов SQLRowCount из
прикладной программы вернет число строк, на которые воздействует инструкция.
Для других инструкций SQL драйвер возвращает любой набор результатов, и код
возврата SQLExecute или SQLExecDirect обычно единственный источник информации
относительно того, была ли инструкция успешно выполнена.
Прикладные программы требуют метаданных для большинства операций с набором
результатов. Например, прикладная программа использует тип данных столбца,
чтобы определить, какую переменную связать с этим столбцом. Это использует
байт длины символьного столбца, чтобы определить, сколько места нужно, чтобы
отобразить данные из этого столбца. Как прикладная программа определяет
метаданные для столбца, зависит от типа прикладной программы.
SQLDescribeCol и SQLColAttribute (SQLColAttributes в случае MyODBC 2.50)
используются, чтобы получить набор метаданных. Различие между этими двумя
функциями в том, что SQLDescribeCol всегда возвращает те же самые пять частей
информации (имя столбца, тип данных, точность, масштаб и допустимость null), а
вот SQLColAttribute возвращает часть информации, запрошенную прикладной
программой. Однако, SQLColAttribute может возвращать намного более богатый
набор метаданных, включая чувствительность столбца к регистру, размер
отображения, возможность поиска и тому подобное.
Чтобы получить строку данных из набора результатов, прикладная программа:
- Вызывает SQLBindCol, чтобы связать столбцы набора результатов с адресами
в памяти, если это еще не сделано.
- Вызывает SQLFetch, чтобы перейти на следующую строку в наборе
результатов и получить данные для всех столбцов.
Данные, выбранные из сервера MySQL, возвращены прикладной программе
драйвером в переменных, которые прикладная программа распределила для этой
цели. Прежде, чем это может быть выполнено, прикладная программа должна
связать эти переменные со столбцами набора результатов, используя SQLBindCol.
Прикладные программы могут связать столько столбцов набора результатов,
сколько сочтут нужным. Когда строка данных выбрана, драйвер возвращает данные
для связанных столбцов прикладной программе. Данные могут быть выбраны и из
несвязанных столбцов, вызывая SQLGetData. Это обычно делается, чтобы получить
длинные данные, которые часто превышают длину одиночного буфера, и должны быть
получены по частям.
Переменная остается связанной со столбцом до тех пор, пока столбец не будет
отвязан явно вызовом SQLBindCol с указателем null в качестве адреса
переменной, или пока не вызвана функция SQLFreeStmt с опцией SQL_UNBIND.
Курсор представляет собой инструмент, который позволяет Вам построчно
проходить через набор результатов. Прикладные программы могут выполнять много
действий на каждой индивидуальной строке в данном наборе результатов. Курсор
открыт на наборе результатов выполнением запроса. Курсор в наборе результатов
указывает текущую (актуальную) позицию и то, какая строка будет возвращена.
MyODBC поддерживает работу с двумя типами курсоров, а именно с
блочным и со скроллируемым.
Прикладная программа может выбирать много строк данных, используя одну
инструкцию выборки через блочный курсор. Строки, возвращенные в одиночной
выборке с блочным курсором, названы rowset. Важно не путать rowset с набором
результатов. Набор результатов поддерживается сервером MySQL, в то время как
rowset поддерживается драйвером в буферах прикладных программ. В то время как
набор результатов фиксирован, rowset меняет позицию и удовлетворяет каждый раз
новому набору строк. Прикладная программа устанавливает размер rowset,
используя SQLSetStmtAttr с опцией SQL_ATTR_ROW_ARRAY_SIZE.
MyODBC 3.51 три типа скроллируемых курсоров, используя которые прикладная
программа может двигаться в наборе результатов:
- Только вперед
- Статический
- Динамический (только для MyODBC 3.51.01 и выше)
Чтобы работать с динамическим курсором, надо проверить опцию "Enable
Dynamic Cursor Type" в настройках DSN или передать в строке подключения
параметр OPTION=32.
Прикладная программа может устанавливать тип курсора через SQLSetStmtAttr
(или SQLSetStmtOption в драйвере MyODBC 2.50) с опцией SQL_ATTR_CURSOR_TYPE.
По умолчанию драйвер неявно использует курсор типа "только вперед".
Применяя курсор типа "только вперед", прикладная программа может идти
только вперед в наборе результатов и не может вернуться назад. В статическом
типе курсора прикладная программа может продвигаться вперед, назад или вообще
к любому желательному расположению в наборе результатов.
При использовании скроллируемых курсоров, прикладные программы вызывают
SQLFetchScroll (или SQLExtendedFetch для MyODBC 2.50), чтобы установить курсор
и строки выборок. SQLFetchScroll поддерживает как относительную (следующая
строка, предыдущая строка и переход на n строк), так и абсолютную (первая
строка, последняя строка и строка n) прокрутку (скроллинг). Параметры
FetchOrientation и FetchOffset в вызове функции SQLFetchScroll определяют,
который rowset выбрать.
FetchOrientation |
Значение |
SQL_FETCH_NEXT |
Вернет следующий rowset. Это эквивалентно вызову SQLFetch.
SQLFetchScroll игнорирует значение FetchOffset. |
SQL_FETCH_PRIOR |
Вернет предшествующий rowset. SQLFetchScroll игнорирует значение
FetchOffset. |
SQL_FETCH_FIRST |
Вернет первый rowset в наборе результатов. SQLFetchScroll игнорирует
значение FetchOffset. |
SQL_FETCH_LAST |
Вернет последний полный rowset в наборе результатов. SQLFetchScroll
игнорирует значение FetchOffset. |
SQL_FETCH_ABSOLUTE |
Вернет rowset, начинающийся в строке FetchOffset. |
SQL_FETCH_RELATIVE |
Вернет FetchOffset строк от начала текущего
rowset. |
Обратите внимание, что при использовании типа курсора "только вперед",
прикладная программа может только продвигаться на SQL_FETCH_NEXT в то время,
как при использовании статических и/или динамических типов можно переходить в
любое желательное расположение.
Прикладные программы могут модифицировать или удалять желательные строки в
наборе результатов, используя следующий набор обращений ODBC:
- Вызовом
SQLSetPos
- Выполнением позиционных команд SQL, используя
SQLExecute
или SQLExecDirect
.
Чтобы использовать позиционное удаление или модификацию, прикладная
программа должна:
- Установить имя курсора, вызывая SQLSetCursorName. Если прикладная
программа не установила имя курсора явно, то драйвер возвращает заданное по
умолчанию имя курсора.
- Открыть набор результатов инструкцией SELECT.
- Установить курсор в строку, которую нужно модифицировать или удалить.
Прикладная программа может делать это, вызывая SQLFetchScroll (или
SQLExtendedFetch в случае MyODBC 2.50), чтобы получить rowset, содержащий
требуемую строку, и вызывая SQLSetPos с SQL_POSITION, чтобы установить
курсор в эту строку в рамках rowset.
- Получить имя курсора, вызывая SQLGetCursorName. Обратите внимание, что,
если прикладная программа не устанавливает имя курсора явно перед открытием
набора результатов в том же самом операторном дескрипторе через вызов
функции SQLSetCursorName, драйвер возвращает заданное по умолчанию имя
курсора.
- Прикладная программа выполняет позиционную инструкцию на другом
операторном дескрипторе, чем тот, который используется набором результатов.
Синтаксис этих инструкций:
UPDATE table-name SET column-identifier = {expression | NULL}
[, column-identifier = {expression | NULL}]...
WHERE CURRENT OF cursor-name
DELETE FROM table-name WHERE CURRENT OF cursor-name
Здесь cursor-name
задает имя курсора, возвращенное
SQLGetCursorName.
Пример:
HSTMT hstmtSelect;
HSTMT hstmtUpdate;
UCHAR szLname[NAME_LEN],szFname[NAME_LEN],cursorName[10];
SWORD cursorLen;
SDWORD cbName;
/* Allocate the statement handles */
retcode = SQLAllocStmt(hdbc, &hstmtSelect);
retcode = SQLAllocStmt(hdbc, &hstmtUpdate);
/* SELECT the result set and bind its columns to local storage */
retcode = SQLExecDirect(hstmtSelect,
"SELECT lname,fname FROM EMP", SQL_NTS);
retcode = SQLBindCol(hstmtSelect,
1, SQL_C_CHAR, szLname, NAME_LEN,
&cbLname);
retcode = SQLBindCol(hstmtSelect, 2, SQL_C_CHAR, szFname, NAME_LEN,
&cbFname);
/* get the cursor name */
retcode = SQLGetCursorName(hstmtSelect, cursorName,
10, &cursorLen);
/* Position to third row in the result set */
retcode = SQLFetchScroll(hstmtSelect,SQL_FETCH_ABSOLUTE, 3);
if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO));
/* Perform a positioned update */
sprintf(updsql,
"UPDATE EMP SET fname = 'monty' WHERE CURRENT OF %s",
cursorName);
retcode = SQLExecDirect(hstmtUpdate, updsql, SQL_NTS);
Прикладные программы могут модифицировать или удалять любую строку в
текущем (актуальном) rowset, используя SQLSetPos. Это удобный вариант для
построения и выполнения инструкции SQL.
SQLSetPos функционирует на текущем (актуальном) rowset и может
использоваться только после обращения к SQLFetchScroll или SQLExtendedFetch.
Прикладная программа определяет номер строки, которую надо модифицировать,
удалить или вставить, и драйвер получает новые данные для этой строки из
буферов rowset. SQLSetPos может также использоваться, чтобы обозначить
определенную строку как текущую или обновить специфическую строку в rowset из
источника данных.
Размер Rowset может быть установлен обращением к SQLSetStmtAttr с опцией
SQL_ATTR_ROW_ARRAY_SIZE.
Первая строка в rowset имеет номер 1. Параметр RowNumber в SQLSetPos должен
идентифицировать строку в rowset. В смысле, значение должно быть в диапазоне
между 1 и числом строк, которые были выбраны в последний раз (что может быть
меньше, чем размер rowset). Маленькая хитрость: если RowNumber равен 0,
операция будет применяться к каждой строке в rowset.
Модификация строк в rowset:
Операция SQLSetPos с
параметром SQL_UPDATE предписыает серверу модифицировать одну или более
выбранных строк таблицы, используя данные в буферах прикладных программ для
каждого связанного столбца.
Чтобы модифицировать строки с SQLSetPos, прикладная программа делает
следующее:
- Помещает новые значения данных в буфера rowset.
- Устанавливает значение в буфере длин каждого столбца по мере
необходимости. Это байт длины данных или SQL_NTS для столбцов, связанных со
строковыми буферами, или SQL_NULL_DATA для любых столбцов, которые будут
установлены в NULL.
- Вызывает SQLSetPos с параметром Operation установленным в SQL_UPDATE и
RowNumber равным числу строк для обновления. Маленькая хитрость: если
RowNumber равен 0, операция будет применяться к каждой строке в
rowset.
После завершения SQLSetPos текущей строкой будет модифицируемая строка.
Прикладная программа может проверять общее количество строк, на которые
воздействует инструкция update, вызывая SQLRowCount и статус обновления через
атрибут SQL_ATTR_ROW_STATUS_PTR.
Удаление строк:
Параметр SQL_DELETE в SQLSetPos
предписывает серверу удалить одну или несколько строк в таблице. Чтобы удалить
строки с помощью SQLSetPos, программа вызывает SQLSetPos с параметром
Operation, установленным в SQL_DELETE и RowNumber равным числу удаляемых
строк. Осторожно: если RowNumber равен 0, будут удалены все строки.
После завершения SQLSetPos, удаленная строка становится текущей, и
состояние равно SQL_ROW_DELETED. Строка не может использоваться в любых
дальнейших позиционных операциях.
Сервер MySQL поддерживает синтаксис SHOW SQL, чтобы
обеспечить информацию относительно баз данных, таблиц, столбцов или состояния
сервера. Прикладные программы ODBC могут получать метаинформацию относительно
сервера, используя следующие функции каталога:
Функция |
Описание |
SQLTables |
Возвращает список каталогов (баз данных), таблиц или типы
таблиц. |
SQLColumns |
Возвращает список столбцов в одной или нескольких таблицах. |
SQLStatistics |
Возвращает список статистики относительно одной таблицы. Также
возвращает список индексов, связанных с этой таблицей. |
SQLSpecialColumns |
Возвращает список столбцов, который уникально идентифицирует строку
в одной таблице. Также возвращает список столбцов, которые автоматически
модифицируются в этой таблице. |
SQLPrimaryKeys |
Возвращает список столбцов, которые составляют первичный ключ в
одной таблице. |
SQLForeignKeys |
Возвращает список внешних ключей в одной таблице или список внешних
ключей в других таблицах, которые обращаются к ней. |
SQLTablePrivileges |
Возвращает список привилегий, связанных с таблицей или несколькими
таблицами сразу. |
SQLColumnPrivileges |
Возвращает список привилегий, связанных с одним или несколькими
столбцами только в одной таблице. |
SQLGetTypeInfo |
Возвращает список типов данных SQL, поддерживаемых сервером. Эти
типы данных используются в командах CREATE TABLE и ALTER
TABLE. |
Транзакция представляет собой последовательность инструкций SQL, которые
формируют логический модуль. Каждая инструкция SQL в транзакции выполняет
часть задачи, и все они необходимы для выполнения некоего задания. Только
когда все инструкции SQL в транзакции выполнены успешно, задачу можно
обрабатывать как завершенную. Имеется общее управление потоком данных в
транзакции:
- Звауск транзакции
- Выполнение транзакции
- Завершение или отмена транзакции
По умолчанию MyODBC/MySQL работает в режиме autocommit. Это означает, что
как только Вы выполняете инструкцию SQL, MySQL сохранит данные на диске:
механизм транзакций выключен. Если Вы используете транзакционно-безопасные
таблицы (например, BDB или InnoDB), Вы можете перевести MySQL в режим
не-autocommit с командой SQL:
SET AUTOCOMMIT=0
Через MyODBC Вы можете устанавливать AUTOCOMMIT в ON или в OFF, используя
SQLSetConnectAttr (или SQLSetConnectOption в MyODBC 2.50) с атрибутом
SQL_ATTR_AUTOCOMMIT. После этого Вы должны использовать SQLEndTran (или
SQLTransact в MyODBC 2.50) для завершения транзакции или ее отмены (если Вы
хотите игнорировать изменения, которые Вы сделали, начиная с начала Вашей
транзакции), используя опции SQL_COMMIT или SQL_ROLLBACK.
Пример:
прикладная программа делает следующий набор
операций, чтобы показать транзакционное поведение:
- Создает таблицу типа BDB или типа InnoDB.
- Выключает режим AUTOCOMMIT.
- Вставляет строку данных и завершает транзакцию.
- Вставляет вторую строку данных и отменяет эту транзакцию.
- Теперь Вы должны видеть только одну (первую) строку данных в
таблице.
Вы можете попробовать сделать то же самое с InnoDB, меняя тип таблицы.
SQLHDBC hdbc;
SQLHSTMT hstmt;
/* Set AUTOCOMMIT to OFF */
SQLSetConnectOption(hdbc,SQL_AUTOCOMMIT,SQL_AUTOCOMMIT_OFF);
/* CREATE TABLE t_tran of TYPE BDB */
SQLExecDirect(hstmt,"drop table if exists t_tran",SQL_NTS);
SQLTransact(NULL,hdbc,SQL_COMMIT);
SQLExecDirect(hstmt,"create table t_tran(col1 int, col2 varchar(30))
TYPE= BDB",SQL_NTS);
SQLTransact(NULL,hdbc,SQL_COMMIT);
/* INSERT A ROW OF DATA */
SQLExecDirect(hstmt,"insert into t_tran values(10,'venu')",SQL_NTS);
/* Now, commit the insert */
SQLTransact(NULL,hdbc,SQL_COMMIT);
/* Again INSERT second row of data */
SQLExecDirect(hstmt,"insert into t_tran values(20,'mysql')",SQL_NTS);
/* Rollback the previous INSERT */
SQLTransact(NULL,hdbc,SQL_ROLLBACK);
/* Now FETCH bac and check whether it has one row or not. */
SQLFreeStmt(hstmt,SQL_CLOSE);
SQLExecDirect(hstmt,"select * from t_tran",SQL_NTS);
SQLFetch(hstmt);
assert(SQLFetch(hstmt) == SQL_NO_DATA_FOUND);
SQLFreeStmt(hstmt,SQL_CLOSE);
Обратите внимание, что если Вы используете драйвер MyODBC 3.51, замените
SQLSetConnectOption на SQLSetConnectAttr, а SQLTransact на SQLEndTran.
Все функции в MyODBC возвращают диагностическую информацию двумя способами.
Код возврата функции указывает полный успех, сбой или другую релевантную
информацию о функции. Если прикладная программа хочет получить
детализированную информацию относительно функционального состояния, то
диагностические записи это легко обеспечивают. Диагностическая информация
используется, чтобы отследить ошибки программирования, типа недопустимых
дескрипторов), недопустимой функциональной последовательности и ошибок
синтаксиса в инструкциях SQL. Это также используется во время выполнения,
чтобы перехватить ошибки во время выполнения программы и предупреждения типа
усечения данных, нарушений прав доступа и ошибок синтаксиса в инструкциях SQL,
введенных пользователем.
Коды возврата:
каждая функция в ODBC возвращает код,
известный как код возврата. Следующее представляет собой различные коды
возврата, возвращаемые MyODBC.
Код возврата |
Описание |
SQL_SUCCESS |
Все в порядке. |
SQL_SUCCESS_WITH_INFO |
Все в порядке, но некоторая информация возвращается в качетсве
предупреждения. Прикладная программа может вызывать SQLGetDiagRec (или
SQLError для MyODBC 2.50) или SQLGetDiagField, чтобы получить
дополнительную информацию. |
SQL_ERROR |
Ошибка: функция провалилась. Прикладная программа может вызывать
SQLGetDiagRec (или SQLError для MyODBC 2.50) или SQLGetDiagField, чтобы
получить дополнительную информацию. |
SQL_NO_DATA |
Данные не могут быть получены (конец набора?). |
SQL_NO_DATA_FOUND |
Это синоним для SQL_NO_DATA в случае MyODBC 2.50. |
SQL_INVALID_HANDLE |
Недопустимый дескриптор был обнаружен. Это указывает на ошибку
программирования. |
SQL_NEED_DATA |
Драйвер указывает, что прикладная программа должна послать значения
данных в качестве параметра времени выполнения. |
Когда происходит ошибка в прикладной программе, то есть когда функция
возвратит SQL_ERROR или SQL_SUCCESS_WITH_INFO, прикладная программа может
запрашивать диагностическую информацию, вызывая функции SQLGetDiagRec или
SQLGetDiagField из драйвера. В MyODBC 2.50 прикладная программа может
использовать SQLError для выполнения этой работы. При использовании драйвера
MyODBC 3.51, прикладная программа может запрашивать большее количество
диагностических записей, используя SQLGetDiagField.
Применение SQLGetDiagRec и SQLGetDiagField:
Как описано
в предыдущем разделе, прикладные программы вызывают SQLGetDiagRec или
SQLGetDiagField, чтобы получить диагностическую информацию в случае драйвера
MyODBC 3.51. Эти функции принимают среду, подключение, инструкцию или
дескриптор и возвращают диагностику из функции, которая последней использовала
этот дескриптор.
Прикладные программы получают индивидуальные диагностические поля, вызывая
SQLGetDiagField и определяя поле, которое надо получить. Некоторые поля не
имеют никакого значения для определенных типов дескрипторов.
Прикладные программы получают и SQLSTATE, местный код ошибки и
диагностическое сообщение в одном обращении, вызывая SQLGetDiagRec.
Пример: рассмотрим для примера ситуацию, где пользователь
пробует удалить несуществующую таблицу, драйвер возвращает SQL_ERROR, а
прикладная программа может выбирать диагностическую информацию, используя
вызов функции SQLGetDiagRec.
SQLCHAR SqlState[6],
SQLCHAR ErrorMsg[SQL_MAX_MESSAGE_LENGTH];
SQLINTEGER NativeError;
SQLSMALLINT MsgLen;
SQLRETURN sql_return, diag_return;
SQLHSTMT hstmt;
// Drop a non-existing table
sql_return=SQLExecDirect(hstmt, "DROP TABLE NON_EXISTANT_TABLES^&*",
SQL_NTS);
if (sql_return == SQL_SUCCESS_WITH_INFO || sql_return == SQL_ERROR)
{
// Get the diag information.
Diag_return = SQLGetDiagRec(SQL_HANDLE_STMT, hstmt, 1, SqlState,
&NativeError, ErrorMsg, sizeof(ErrorMsg),
&MsgLen);
if (diag_return != SQL_NO_DATA)
{
DisplayError(SqlState,NativeError,Msg,MsgLen);
}
}
содержание назад вперед