Грабли оператора 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]Понравилась статья? Расскажите о ней друзьям: