Грабли оператора HANDLER

версия для печати

Сервер MySQL 5.1. Есть в его реализации замечательный оператор HANDLER. Он обеспечивает прямой доступ к интерфейсу обработчика таблиц MyISAM и InnoDB, минуя оптимизатор SQL. Следовательно, этот оператор работает быстрее, чем SELECT. Прежде чем показать, где проблема, коротко расскажу о синтакисе оператора. Далее копипаст справки по MySQL, ничего нового нет, причем я уберу из нее не относящее к дело.

HANDLER tbl_name OPEN [ AS alias ]
HANDLER tbl_name READ index_name { = | >= | <= | < }(value1,value2,...)[ WHERE ... ] [LIMIT ... ]
HANDLER tbl_name READ index_name { FIRST | NEXT | PREV | LAST } [ WHERE ... ] [LIMIT ... ]
HANDLER tbl_name CLOSE

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

Вторая форма выбирает одну строку (или больше - в соответствии с установкой в выражении LIMIT), для которой(ых) указанный индекс соответствует заданному условию и условие в выражении WHERE также выполняется.

Третья форма выбирает одну строку (или больше - в соответствии с установкой в выражении LIMIT), из таблицы; в порядке указания индексов в соответствии с условием WHERE.

Оператор HANDLER ... CLOSE закрывает таблицу, открытую оператором HANDLER ... OPEN.

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

HANDLER `table` OPEN
HANDLER `table` READ `index_field`=`value`
HANDLER `table` CLOSE
Теперь по теме

Главная, на мой взгляд, прелесть оператора - возможность читать соседние записи от текущей. Но именно здесь лежат грабли! Создадим таблицу:

CREATE TABLE `test` (
  `id` tinyint(1) NOT NULL,
  `rec_date` date NOT NULL,
  `text` char(45) NOT NULL,
  PRIMARY KEY (`id`),
  KEY `date` (`rec_date`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

INSERT INTO `test` VALUES ('1', '2011-07-08', 'Запись 1');
INSERT INTO `test` VALUES ('2', '2011-07-01', 'Запись 2. По дате раньше первой.');
INSERT INTO `test` VALUES ('3', '2011-07-22', 'Запись 3. Самая последняя по дате/индексу');

SELECT * FROM `test`;
Результатом будет следующее:
mysql> SELECT * FROM `test`;
+----+------------+-------------------------------------------+
| id | rec_date   | text                                      |
+----+------------+-------------------------------------------+
|  1 | 2011-07-08 | Запись 1                                  |
|  2 | 2011-07-01 | Запись 2. По дате раньше первой.          |
|  3 | 2011-07-22 | Запись 3. Самая последняя по дате/индексу |
+----+------------+-------------------------------------------+

Теперь мне нужно найти запись по дате (2011-07-08) и получить запись, следующую за ней по полю id. Выполняем серию запросов:

HANDLER `test` OPEN;
HANDLER `test` READ `date`=('2011-07-08');
HANDLER `test` READ `PRIMARY` NEXT;
HANDLER `test` CLOSE;
Результат получается такой: rslt1: id.1   rec_date.'2011-07-08'
rslt2: id.3   rec_date.'2011-07-22' //следующий по дате!
но т.к. в третьей строке указано "читать по первичному ключу", то должно быть: rslt1: id.1   rec_date.'2011-07-08'
rslt2: id.2   rec_date.'2011-07-01' //следующий по id

Пробовал в третью строку указывать другие индексы (не в этом примере) - без разницы. Следующая запись по индексу даты и ниипет! Этот момент может оказаться не хилыми граблями на пути к совершенству кода %)

[1oo%, EoF]

Понравилась статья? Расскажите о ней друзьям:

Метки: MySQL, кодинг

Комментарии
Для работы модуля комментариев включите javaScript


Показать/скрыть правила
Имя
[i] [b] [u] [s] [url]
:-) ;-) :D *lol* 8-) :-* :-| :-( *cry* :o :-? *unsure* *oops* :-x *shocked* *zzz* :P *evil*

Осталось 1000 символов.
Код защиты от спама Обновить код
Каждый комментарий проходит ручную модерацию. 100% фильтрация спама.
Продвижение
Время
Метки