English Version

Глава 4. Смешанные случаи.

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

Например, на каком-то шаге сценария вы начинаете получать неверные данные. После анализа запроса (или запросов) SELECT выясняется, что запросы корректны и возвращают именно те данные, которые есть в таблице (или таблицах).

Это обозначает, что неверные данные были внесены на ранних этапах сценария.

Как выяснить когда именно это было сделано?

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

Можно рассматривать пример со списком из первой главы как образец такого неверного поведения.

Посмотрим ещё раз на вывод.

Имеющиеся системы

* Учебник
* Тест
* test2
* test2
* test2
* test2
* test2

Введите название новой системы:
<>
Описание:
<>

<Go!>

Мы рассматривали страницу, модифицирующую список. Но что если подобный список обнаружился на странице, осуществляющей вывод? Вот код, отвечающий за вывод списка:

return $this->addParameters(array(Field::ITEMS => DAO::system()->getPlainList()));

Запрос SELECT будет совершенно корректным:

SELECT `system`.`id`, `system`.`name`, `system`.`description` FROM `system`

Посмотрим что в таблице:

mysql> select * from system;
+----+---------+-------------------------------------------------+
| id | name    | description                                     |
+----+---------+-------------------------------------------------+
|  1 | Учебник  | Конструирование мужской и женской одежды             |
|  2 | Тест     | Тестовый геометрический набор                        |
|  3 | test2   | New test                                        |
|  4 | test2   | foobar                                          |
|  8 | test2   |                                                 |
+----+---------+-------------------------------------------------+
5 rows in set (0.00 sec)

Соответственно мы будем должны вернуться на шаг раньше, когда мы добавляли новый элемент списка, с тем чтобы найти источник проблем, что мы и проделали ранее в главе №1.

Приём №7: проверяйте ваш сценарий шаг за шагом в обратном порядке пока не найдёте проблемный запрос.

Длинно, не правда ли? Можно ли что-то сделать, чтобы выявить проблему более простым способом?

Да. Все запросы, в том числе и DML, всегда возвращают результат. Обязательно проверяйте его! Также проверяйте ошибки и предупреждения, которые возвращают запросы. Как правило проблемный запрос ошибочен, но непроверенный результат приводит к тому, что он остался незамеченным. Используйте средства вашего любимого языка программирования для проверки результата и ошибок.

MySQL возвращает следующие данные для DML запросов:

mysql> update system set name='test3' where id=8;
Query OK, 1 row affected (0.55 sec)
Rows matched: 1 Changed: 1 Warnings: 0

Ниже я подробно объясню что обоначает эта информация и дам указания как получить её не только в командной строке, но и в приложении. Я буду использовать синтакс C API. В случае альтернативных коннекторов функции будут называться, скорее всего, аналогично C API вариантам. JDBC, который использует Connector/J и ODBC имеют собственные интерфейсы для получения нужной информации. Используйте их!

Обратите внимание на следующее:

Query OK, N row affected

Запрос выполнен, N строк обновлено.

C API:

Используйте функцию

mysql_affected_rows()
чтобы получить эту информацию в вашем приложении.

Rows matched: M

Найдено M совпадающих строк.

C API:

Функция

mysql_info()
возвращает дополнительную информацию о последнем запросе в виде строки.

Changed: P

Из них изменено P строк. Обратите внимание, что M и P могут отличаться: MySQL замечает, когда обновлять ничего не надо и не делает лишней работы.

C API:

Функция

mysql_info()
возвращает дополнительную информацию о последнем запросе в виде строки.

Warnings: R

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

В вашей программе вы можете использовать следующие функции:

C API:

mysql_info()
- возвращает дополнительную информацию о последнем запросе в виде строки.
mysql_warning_count()
- сколько предупреждений вернул предыдущий запрос
mysql_sqlstate()
- последний SQLSTATE. «0000» обозначает 0 ошибок и предупреждений

Также полезно проверять ошибку. Используйте следующие функции:

C API:

mysql_errno()
- номер ошибки MySQL
mysql_error()
- ошибка в текстовом виде

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

Приём №8: всегда проверяйте результат запроса! Используйте инструменты вашего коннектора или вывод интерактивного клиента.

К сожалению существуют случаи, когда именно незамеченная логическая ошибка в DML запросе приводит к выводу неверных данных. Часто это можно заметить сравнивая значение affected rows с ожидаемым, но иногда его не просто спрогнозировать. В этом случае поможет только приём №7.

Назад Содержание Вперёд



Автор 2009 Света Смирнова
COPYRIGHT © 2009 С.Смирнова и С.Ласунов
sveta_гав_js-client_точка_com