В разработке на платформе 1С часто возникает вопрос: нужно ли проверять результат запроса на пустоту с помощью метода Пустой() перед тем, как начать его обрабатывать через Выбрать()? Многие разработчики, особенно начинающие, полагают, что вызов РезультатЗапроса.Выбрать() — это ресурсоемкая операция, и чтобы избежать лишней нагрузки, стоит сначала убедиться, что запрос вообще вернул какие-то данные. Давайте разберемся, так ли это на самом деле, и проанализируем, в каких случаях проверка на пустоту оправдана, а в каких является избыточной и лишь загромождает код.
Чтобы понять логику использования методов, давайте посмотрим, что происходит "под капотом", когда мы выполняем запрос. Этот процесс можно разбить на несколько этапов:
Запрос.Выполнить(): На этом шаге текст вашего запроса отправляется на сервер СУБД (например, MS SQL или PostgreSQL). СУБД выполняет запрос и готовит результирующую таблицу данных. Важно понимать, что в этот момент все данные еще не передаются обратно в 1С. Метод возвращает специальный объект РезультатЗапроса, который, по сути, является "указателем" или курсором на эти данные на сервере.РезультатЗапроса.Пустой(): Этот метод выполняет очень быструю и легковесную операцию. Он просто спрашивает у СУБД: "В результирующей таблице есть хотя бы одна строка?". Он не требует передачи самих данных и поэтому выполняется практически мгновенно.РезультатЗапроса.Выбрать(): Вопреки распространенному мнению, этот метод сам по себе не является ресурсоемкой операцией. Он не загружает все данные в память. Вместо этого он создает другой объект — ВыборкаИзРезультатаЗапроса, который является итератором. Этот итератор готов к последовательному "вытягиванию" строк с сервера.Выборка.Следующий(): А вот здесь и происходит основная работа. При каждом вызове этого метода из СУБД в 1С передается очередная порция данных (одна или несколько строк). Именно этот процесс в цикле потребляет ресурсы, если результат запроса большой.Из этого следует ключевой вывод: создание выборки через Выбрать() само по себе почти ничего не стоит с точки зрения производительности. Поэтому опасения "дернуть лишний раз" этот метод необоснованны.
Проверку на пустоту следует использовать тогда, когда вам не нужно содержимое результата запроса, а важен лишь сам факт его наличия или отсутствия. То есть, когда вам нужен ответ на вопрос "да/нет?".
Рассмотрим практические примеры:
ЕстьОстаткиНаСкладе(Номенклатура, Склад), которая должна вернуть Истина или Ложь.В таких случаях использование Пустой() — самый оптимальный и читаемый способ. Посмотрим на код.
Как делать не стоит:
Создавать выборку, делать один шаг и на основании этого принимать решение. Это неэффективно и избыточно.
Функция ПроверитьНаличиеДоговора(Контрагент)
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ ПЕРВЫЕ 1
| ДоговорыКонтрагентов.Ссылка
|ИЗ
| Справочник.ДоговорыКонтрагентов КАК ДоговорыКонтрагентов
|ГДЕ
| ДоговорыКонтрагентов.Владелец = &Контрагент";
Запрос.УстановитьПараметр("Контрагент", Контрагент);
// Неправильно: создаем выборку только для одной проверки
Выборка = Запрос.Выполнить().Выбрать();
Если Выборка.Следующий() Тогда
Возврат Истина;
Иначе
Возврат Ложь;
КонецЕсли;
КонецФункции
Как правильно:
Использовать метод Пустой(), чтобы получить прямой ответ на свой вопрос. Код становится короче, чище и эффективнее.
Функция ПроверитьНаличиеДоговора(Контрагент)
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ ПЕРВЫЕ 1
| ДоговорыКонтрагентов.Ссылка
|ИЗ
| Справочник.ДоговорыКонтрагентов КАК ДоговорыКонтрагентов
|ГДЕ
| ДоговорыКонтрагентов.Владелец = &Контрагент";
Запрос.УстановитьПараметр("Контрагент", Контрагент);
РезультатЗапроса = Запрос.Выполнить();
// Правильно и лаконично: возвращаем результат проверки
Возврат НЕ РезультатЗапроса.Пустой();
КонецФункции
Проверка является избыточной и вредит читаемости кода, если вам в любом случае нужно будет работать с данными из результата запроса, то есть обходить их в цикле.
Классический пример — заполнение табличной части документа или печатной формы на основе данных запроса. Вам не важно, пустой результат или нет. Если он пустой, цикл просто не выполнится ни разу, и таблица останется пустой. Если данные есть, цикл их обработает. Дополнительная проверка Если НЕ Результат.Пустой() ничего не дает, кроме лишней вложенности кода.
Как делать не стоит (избыточный код):
// Избыточная и ненужная проверка
РезультатЗапроса = Запрос.Выполнить();
Если НЕ РезультатЗапроса.Пустой() Тогда // <-- Этот блок кода лишний
Выборка = РезультатЗапроса.Выбрать();
Пока Выборка.Следующий() Цикл
НоваяСтрока = ТабличнаяЧасть.Добавить();
ЗаполнитьЗначенияСвойств(НоваяСтрока, Выборка);
КонецЦикла;
КонецЕсли;
Как правильно и чисто:
Сразу получаем выборку и запускаем цикл. Если запрос ничего не вернул, метод Выборка.Следующий() сразу вернет Ложь, и тело цикла не будет выполнено. Результат тот же, а код проще.
// Правильный и лаконичный вариант
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
НоваяСтрока = ТабличнаяЧасть.Добавить();
ЗаполнитьЗначенияСвойств(НоваяСтрока, Выборка);
КонецЦикла;
Иногда можно услышать аргумент, что для сложных запросов (например, с несколькими уровнями итогов, иерархией, дополнениями периодов) вызов Выбрать() может быть не таким уж и "легким". Это отчасти верно.
Когда вы создаете иерархическую выборку, например, через Результат.Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам), платформа 1С может выполнять дополнительную обработку для построения дерева группировок. Однако даже в этом случае основная нагрузка все равно ложится на обход этой иерархии, а не на сам факт ее создания. Принцип остается тем же: если вам все равно нужно обходить эту структуру, предварительная проверка на Пустой() не принесет выгоды.
В итоге мы можем сформулировать очень простое и понятное правило, которое поможет вам писать чистый и эффективный код:
НЕ РезультатЗапроса.Пустой().Выбрать() и организуйте цикл обхода, без предварительной проверки на пустоту.Следование этому простому принципу сделает ваш код более лаконичным, читаемым и профессиональным.