Платформы корпоративных информационных систем

         

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



Пример 13-1. Простая программа, извлекающая все данные из тестовой базы и отображающая их

#include <sys/time. h>
#include <stdio.h>
#include <mysql.h>

int main(char **args) {
MYSQL_RES 'result;
MYSQL_ROW row;
MYSQL 'connection, mysql;
int state;

/* соединиться с базой данных mySQL на athens.imaginary.com */

mysql_init(&mysql);

connection = mysql_real_connect(&mysql,



"alMens.imaginary.com",

0, 0,

"db_test", 0, 0);

/* проверить ошибки соединения */
if( connection == NULL ) {

/* вывести сообщение об ошибке */

printf(mysql_error(&mysql));

return 1;

}

state = mysql_query(connection,

"SELECT test_id, test_val FROM test");
if( state != 0 ) {

printf(mysql_error(connection));

return 1; }

/* прежде чем делать другие вызовы,
* необходимо вызвать mysql_store_result()

*/

result = mysql_store_result(connection);
printf("Строк: %d\n", mysql_num_rows(result));
/* обработать каждую строку результирующего набора */
while( ( row = mysql_fetch_row(result)) != NULL )
{
printf("id: %s, значение: %s\n", (row[0] ? row[0] : "NULL"), (row[1] ? row[1] : "NULL")); }

/* освободить ресурсы, использовавшиеся результирующим набором */
mysql_free_result(result); /* закрыть соединение */
mysql_close(connection);
printf("Koнец, работы.\n");
}

Назначение файлов mysql.h и stdio.h, включаемых директивой ftinclude, должно быть очевидно. Файл заголовков mysql.h содержит прототипы и переменные, необходимые для MySQL, a stdio.h содержит прототип для printf (). Файл заголовков sys/time.h приложением фактически не используется. Он нужен из-за mysql.h, так как файл для MySQL использует определения из sys/time.h, не включая их. Для компиляции программы с помощью компилятора GNU С используйте командную строку:

gcc -L/usr/local/mysql/lib -I/usr/local/mysql/include -о select

select.c\

-Imysql -Insl -Isocket

Разумеется, в этой строке вместо /usr/local/mysql нужно задать тот каталог, в который вы установили MySQL.

Функция main() выполняет те шаги, которые мы перечислили раньше: соединяется с сервером, выбирает базу данных, выдает запрос, обрабатывает его результаты и освобождает использованные ресурсы. По ходу главы мы подробно остановимся на каждом из этих этапов. Сейчас посмотрите на этот код, лишь для того чтобы почувствовать, как он работает. Кроме того, сравните этот пример с той же программой, написанной для mSQL, которая представлена в примере 13-2.*

Пример 13-2. Простое приложение выборки данных для mSQL

#include <sys/time.h>
#include <stdio.h>
#include <msql.h>

int main(char **args) {

int connection, state;

m_result *result;

m_row row;

/* соединиться с базой данных mSOL на athens.imaginary.com */

state = msqlConnect("athens.imaginary.com");

/* проверить ошибки соединения */

if( state == -1 )
{

/* вывести сообщение об ошибке, хранящееся в MsqlErrMsg */
printf(msqlErrMsg);
return 1;
}
else
{

/* описателем соединения является значение, возвращаемое msqlConnect() */

connection = state; }

/* выбрать используемую базу данных */
state = msqlSelectDB(connection, "db_test");
/* опять-таки, -1 указывает на ошибку */
if( state == -1 )
{
printf(msqlErrMsg);

/* закрыть соединение перед выходом */

msqlClose(connection);

return 1; }

state = msqlQuery(connection, "SELECT test_id, test_val FROM test");
if( state == -1 )
{

printf(msqlErrMsg);

return 1;
}
else
{

printf("Строк: %d\n", state);
}

/* прежде чем делать новый вызов Query(),
* необходимо вызвать msqlStoreResult()

*/
result = msqlStoreResult();

/* обработать каждую строку результирующего набора */
while( ( row = msqlFetchRow(result)) != NULL )
{
printf("id: %s, значение: %s\n",

(row[0] ? row[0] : "NULL"),

(row[1] ? row[1] : "NULL"));
}

/* освободить ресурсы, использовавшиеся результирующим набором */
msqlFreeResult(result); /* закрыть соединение */
msqlClose(connect ion);
printf("Конец работы.\n"); }

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

  • В MySQL соединение осуществляется за один шаг, а в mSQL - за два.*
  • Для MySQL требуются имя пользователя и пароль, а для mSQL -нет.
Как указывалось ранее в этой книге, MySQL поддерживает сложную схему авторизации с именами пользователей и паролями. Напротив, в mSQL применяется простая система, использующая ID пользователя процесса, соединяющегося с базой данных. Более надежная схема MySQL гораздо привлекательнее в среде клиент/сервер, но также и значительно более сложна в администрировании. Для разработчиков приложений она означает необходимость передачи в вызове mysql_real_connect() имени пользователя и пароля при работе с MySQL помимо имени сервера, используемого в mSQL.

Первый аргумент API для установления соединения с MySQL может показаться необычным. По сути, это способ отслеживать все вызовы, иначе никак не связанные с соединением. Например, если вы пытаетесь установить соединение, и попытка неудачна, вам нужно получить сообщение о соответствующей ошибке. Однако функция MySQL
mysql_error() требует задания указателя на действующее соединение с базой данных MySQL. Такое соединение обеспечивается изначально созданным нулевым соединением. Однако у вас должна быть действующая ссылка на это значение в течение всего времени существования вашего приложения - вопрос большой важности в более структурированной среде, чем простое приложение вида «соединился, сделал запрос, закрылся». Примеры на C++ далее в этой главе подробнее рассматривают эту тему.

Два другие различия в API относятся к тому, как производятся обработка ошибок и подсчет числа записей в результирующем наборе. API mSQL создает глобальную переменную для хранения сообщений об ошибках. Из-за многопоточности MySQL такая глобальная переменная не смогла бы действовать в его API. Поэтому в нем используется функция mysql_error() для извлечения сообщений об ошибках, связанных с последней ошибкой, порожденной указанным соединением.

API для соединения и обработки ошибок - два пункта, в которых MySQL отличается от mSQL для обеспечения функциональности, отсутствующей в mSQL. Подсчет числа результирующих записей в mSQL делается иным способом для обеспечения лучшего интерфейса, нежели предоставляемый MySQL. А именно: при посылке SQL-запроса в msqlQuery() возвращается число задействованных строк (или -1 в случае ошибки). Таким образом, подсчет измененных строк при обновлении и строк в возвращаемом результирующем наборе при запросе используют одну и ту же парадигму. В MySQL же приходится использовать различные парадигмы. При запросе на получение данных нужно передать результирующий набор функции mysql_nuoi_rows() , чтобы получить число строк в результирующем наборе. При обновлении нужно вызвать другую функцию API, mysql_affected_rows() . В то время как msqlQuery() возвращает число строк, удовлетворивших предложению WHERE при обновлении, mysql_affected_rows() сообщает о числе фактически измененных строк. И наконец, в mSQL есть метод msqlNumRows() , обеспечивающий тот же интерфейс для подсчета результирующего набора, что и в MySQL, но в нем нет аналога для mysql_affected_rows() .



Содержание раздела