Если вы предпочитаете текстовое сообщение об ошибке, можно вызвать подпрограмму mysql_error, которая вместо кода предоставляет осмысленное текстовое сообщение. Текст сообщения пишется в некоторую внутреннюю область статической памяти, поэтому для сохранения текста ошибки его следует скопировать куда- нибудь.
Вы можете вставить элементарную обработку ошибок в вашу программу для того, чтобы увидеть все это в действии. Возможно, вы уже заметили, что можно столкнуться с проблемой, поскольку подпрограмма mysql_real_connect в случае сбоя возвращает указатель NULL, лишая вас кода ошибки. Если дескриптор подключения сделать переменной, его все же можно получить при аварийном завершении mysql_real_connect.
Далее приведен файл connect2.c, демонстрирующий, как применять структуру дескриптора подключения без динамического выделения памяти для нее, а также как написать некоторый базовый программный код обработки ошибок. Внесенные изменения выделены цветом.
#include <stdlib.h>
#include <stdio.h>
#include "mysql.h"
int main(int argc, char *argv[]) {
MYSQL my_connection;
mysql_init(&my_connection);
if (mysql_real_connect(&my_connection, "localhost", "rick",
"I do not know", "foo", 0, NULL, 0)) {
printf("Connection success\n");
mysql_close(&my_connection);
} else {
fprintf(stderr, "Connection failed\n");
if (mysql_errno(&my_connection)) {
fprintf(stderr, "Connection error %d: %s\n",
mysql_errno(&my_connection), mysql_error(&my_connection));
}
}
return EXIT_SUCCESS;
}
Вы смогли легко решить проблему, устранив перезапись вашего дескриптора подключения результатом, возвращаемым при аварийном завершении mysql_real_connect. И кроме того, это отличный пример еще одного способа применения структур дескрипторов подключения. Вы можете вызвать ошибку, выбрав некорректное имя пользователя или пароль, и получите код ошибки, подобный предлагаемому монитором mysql:
$ ./connect2
Connection failed
Connection error 1045: Access denied for user: 'rick@localhost' (Using password: YES)
$
Выполнение SQL-операторов
Теперь, когда вы можете подключаться к вашей базе данных и корректно обрабатывать ошибки, самое время дать вашей программе реальную работу. У основной функции API, предназначенной для выполнения операторов языка SQL, подходящее имя.
int mysql_query(MYSQL *connection, const char *query);
He слишком сложная? Эта подпрограмма принимает указатель на дескриптор подключения и несколько, хочется надеяться, корректных SQL-операторов в виде текстовой строки (без завершения каждого из них точкой с запятой, как в мониторе mysql). В случае удачного завершения возвращается ноль. Вторую подпрограмму mysql_real_query можно применять при запросе двоичных данных, но в этой главе мы используем только подпрограмму mysql_query.
Для простоты начнем с рассмотрения нескольких SQL-операторов, которые не возвращают данные: UPDATE, DELETE и INSERT.
Еще одна важная функция, которую мы рассмотрим, проверяет количество строк, затронутых запросом:
my_ulonglong mysql_affected_rows(MYSQL *connection);
Первое, что вы, вероятно, заметили в этой функции, — очень необычный тип возвращаемых данных. Из соображений переносимости применяется беззнаковый (unsigned) тип. Когда используется функция printf, рекомендуется приводить его к типу unsigned long (длинное беззнаковое) со спецификатором формата %lu. Эта функция возвращает количество строк, измененных предварительно выполненным запросом UPDATE, INSERT или DELETE. Возвращаемое значение, используемое в MySQL, может вас, озадачить, если у вас есть опыт работы с другими базами данных SQL. СУРБД MySQL возвращает количество строк, действительно измененных обновлением, в то время как многие другие СУБД будут считать запись измененной просто потому, что она соответствует одному из условий WHERE.
В основном в случае функций mysql_ возврат 0 означает отсутствие измененных строк, а положительное значение указывает на реальный результат, обычно количество строк, затронутых оператором.
Сначала следует создать таблицу children в вашей базе данных foo, если вы еще не сделали этого. Удалите (с помощью команды drop) любую существующую таблицу, чтобы быть уверенным в том, что вы имеете дело с чистым определением таблицы, и повторно отправьте идентификаторы, применяемые в столбце AUTO_INCREMENT.
$ mysql -u rick -p foo
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
mysql> DROP TABLE children;
Query OK, 0 rows affected (0.58 sec)
mysql> CREATE TABLE children (
-> childno int(11) AUTO_INCREMENT NOT NULL PRIMARY KEY,
-> fname varchar(30),
-> age int
-> );
Query OK, 0 rows affected (0.09 sec)
mysql>
Теперь добавьте программный код в файл connect2.c, для того чтобы вставить новую строку в вашу таблицу. Назовите эту новую программу insert1.с. Учтите, что разбиение оператора на несколько строк объясняется физической шириной страницы; обычно вы не должны разбивать реальный SQL-оператор, если он не слишком длинный, в этом случае можно применить символ / в конце строки для переноса оставшейся части SQL-оператора на следующую строку.