К статье
Практический материал

Разработка и Конфигурация · 13 мин

Как проверить выборку 1С на пустоту

Способы проверить выборку запроса 1С на пустоту: метод Пустой(), Следующий(), Количество() и ВГраница. Примеры кода, типичные ошибки и рекомендации по производительности.

Проверка выборки на пустоту — одна из самых частых операций при разработке на платформе 1С:Предприятие. Запрос к базе данных может вернуть ноль строк, и если код не учитывает эту ситуацию, программа выдаст ошибку обращения к несуществующему полю или молча запишет в документ пустые значения. Правильная проверка занимает одну строку, но выбор метода влияет и на читаемость кода, и на производительность.

Под «выборкой» обычно понимают результат выполнения запроса — объект типа «ВыборкаИзРезультатаЗапроса», полученный методом Выбрать(), либо таблицу значений, полученную методом Выгрузить(). У этих объектов разный набор методов, поэтому способ проверки зависит от того, как именно вы обрабатываете результат запроса.

Ниже разобраны все рабочие способы: от классического метода Пустой() до проверки через Следующий() и функциональный вариант с выгрузкой в таблицу значений. Для каждого указаны условия применения, примеры кода и подводные камни.

Что считается пустой выборкой и когда проверка обязательна

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

Проверка обязательна в трёх случаях. Первый — когда по данным выборки выполняется запись: без проверки можно создать документ с пустыми реквизитами или записать нулевые суммы. Второй — когда код обращается к полям выборки вне цикла: обращение к полю несуществующей строки вызовет ошибку выполнения. Третий — когда по факту пустоты нужно показать пользователю понятное сообщение вместо технической ошибки платформы.

Важно понимать разницу между ошибкой выполнения запроса и пустым результатом. Синтаксическая ошибка в тексте запроса вызовет исключение ещё на этапе Выполнить(), и проверка на пустоту до неё просто не дойдёт. Пустой результат — это штатный ответ СУБД, который нужно обрабатывать логикой прикладного кода.

Способ 1: метод Пустой() у результата запроса

Самый читаемый и рекомендуемый способ — проверить результат запроса до того, как из него получена выборка. У объекта «РезультатЗапроса» есть встроенный метод Пустой(), который возвращает Истина, если запрос не вернул ни одной строки.

Запрос = Новый Запрос;

Запрос.Текст =

"ВЫБРАТЬ

| Номенклатура.Ссылка КАК Ссылка

|ИЗ

| Справочник.Номенклатура КАК Номенклатура

|ГДЕ

| Номенклатура.Артикул = &Артикул";

Запрос.УстановитьПараметр("Артикул", ИскомыйАртикул);

РезультатЗапроса = Запрос.Выполнить();

Если РезультатЗапроса.Пустой() Тогда

Сообщить("Номенклатура с артикулом " + ИскомыйАртикул + " не найдена");

Возврат;

КонецЕсли;

Выборка = РезультатЗапроса.Выбрать();

Пока Выборка.Следующий() Цикл

// обработка строк

КонецЦикла;

Такой подход позволяет завершить процедуру досрочно и не создавать объект выборки, когда обрабатывать нечего. Это делает код короче и защищает от ситуации, когда дальше по тексту предполагается, что хотя бы одна строка есть.

Обратите внимание: метод Пустой() есть именно у результата запроса, а не у выборки. Вызов Выборка.Пустой() приведёт к ошибке — у объекта «ВыборкаИзРезультатаЗапроса» такого метода нет. Это одна из самых частых ошибок начинающих разработчиков.

Типичные ошибки
01
Вызов Выборка.Пустой() — у выборки нет такого метода, код упадёт с ошибкой; проверять нужно РезультатЗапроса.Пустой()
02
Проверка на пустоту после обращения к полям выборки — сначала код уже упал, проверка стала бессмысленной
03
Игнорирование пустого результата при записи данных — в базу попадают документы с пустыми реквизитами
04
Двойной вызов Следующий() перед циклом — первая строка результата теряется без обработки

Способ 2: проверка через первый вызов Следующий()

Если выборка уже получена, определить пустоту можно по результату первого вызова метода Следующий(). Он возвращает Истина, если удалось перейти к очередной строке, и Ложь, если строк больше нет — в том числе если их не было изначально.

Выборка = РезультатЗапроса.Выбрать();

Если Выборка.Следующий() Тогда

// строка есть, поля доступны

НайденнаяСсылка = Выборка.Ссылка;

Иначе

// выборка пустая

Сообщить("Данные не найдены");

КонецЕсли;

Этот приём идеален, когда по логике задачи ожидается ровно одна строка: поиск элемента справочника по уникальному коду, получение среза последних по регистру сведений, поиск документа по номеру. Проверка и чтение данных объединяются в одну конструкцию без лишних переменных.

Критическое ограничение: вызов Следующий() перемещает указатель выборки. Если вы вызвали его для проверки, а затем запустили обычный цикл Пока Выборка.Следующий() Цикл, первая строка будет пропущена. Поэтому либо обрабатывайте первую строку внутри ветки Если, либо используйте способ с Пустой().

Способ 3: выгрузка в таблицу значений и Количество()

Когда результат запроса нужен многократно — для перебора в разных местах, поиска строк, сортировки — его выгружают в таблицу значений методом Выгрузить(). У таблицы значений проверка на пустоту выполняется через количество строк.

ТаблицаРезультатов = Запрос.Выполнить().Выгрузить();

Если ТаблицаРезультатов.Количество() = 0 Тогда

Возврат;

КонецЕсли;

Для Каждого СтрокаТаблицы Из ТаблицаРезультатов Цикл

// обработка строк

КонецЦикла;

На практике цикл Для Каждого по пустой таблице просто не выполнится ни разу, поэтому формально проверка не всегда обязательна. Но явная проверка нужна, если по факту отсутствия данных требуется отдельная реакция: сообщение пользователю, запись в журнал регистрации, альтернативная ветка алгоритма.

Учитывайте стоимость способа: Выгрузить() материализует весь результат в памяти. Для запросов, возвращающих сотни тысяч строк, это заметный расход памяти и времени. Если цель — только проверить наличие данных, выгружать таблицу не нужно, достаточно Пустой().

Сравнение способов проверки

РезультатЗапроса.Пустой()

Универсальный и самый быстрый вариант. Подходит всегда, когда результат ещё не выгружен. Не работает у объекта выборки.

Выборка.Следующий()

Лучший вариант, когда ожидается одна строка: проверка и чтение совмещены. Опасен при последующем цикле — первая строка теряется.

ТаблицаЗначений.Количество() = 0

Подходит, когда данные нужны многократно. Минус — полная материализация результата в памяти.

Запрос с ВЫБРАТЬ ПЕРВЫЕ 1

Оптимален, когда нужен только факт наличия данных по сложному условию без чтения самих данных.

Как проверить наличие данных без выборки: ПЕРВЫЕ 1 и функциональный запрос

Часто задача формулируется шире: не «обработать выборку», а «узнать, есть ли вообще такие данные». Например, перед массовой обработкой проверить, есть ли непроведённые документы за период. В этом случае эффективнее написать отдельный лёгкий запрос с ограничением ПЕРВЫЕ 1.

Запрос = Новый Запрос;

Запрос.Текст =

"ВЫБРАТЬ ПЕРВЫЕ 1

| РеализацияТоваровУслуг.Ссылка КАК Ссылка

|ИЗ

| Документ.РеализацияТоваровУслуг КАК РеализацияТоваровУслуг

|ГДЕ

| РеализацияТоваровУслуг.Дата МЕЖДУ &НачалоПериода И &КонецПериода

| И НЕ РеализацияТоваровУслуг.Проведен";

Если Запрос.Выполнить().Пустой() Тогда

Сообщить("Непроведённых документов за период нет");

КонецЕсли;

Ограничение ПЕРВЫЕ 1 заставляет СУБД остановить поиск после первой найденной строки, а не сканировать всю выборку. На больших таблицах разница во времени выполнения может быть существенной. Чем сложнее условие отбора, тем выгоднее такой подход по сравнению с полным запросом и последующей проверкой.

Альтернатива без запроса вообще — методы поиска встроенного языка: НайтиПоКоду(), НайтиПоНаименованию(), НайтиПоРеквизиту() у менеджеров справочников и документов. Если элемент не найден, они возвращают пустую ссылку, и проверка сводится к сравнению: Если НайденнаяСсылка.Пустая() Тогда. Это быстрее и короче для поиска по индексированным реквизитам.

Особые случаи: итоги, группировки и временные таблицы

Запрос с итогами без группировки

Запрос вида ВЫБРАТЬ СУММА(Сумма) ИТОГИ без предложения СГРУППИРОВАТЬ ПО вернёт одну строку даже при отсутствии данных — со значением NULL в агрегатном поле. Метод Пустой() при этом покажет Ложь, что обманчиво. Проверять нужно само значение: сравнивать с NULL через функцию ЕСТЬNULL() в тексте запроса или на Неопределено/NULL в коде.

Обход иерархических выборок

При обходе результата с группировками (ОбходРезультатаЗапроса.ПоГруппировкам) вложенная выборка по детальным записям может оказаться пустой, даже если группировка существует. Проверку на пустоту нужно выполнять на каждом уровне обхода, а не только для выборки верхнего уровня.

Пакетные запросы и временные таблицы

Если запрос содержит пакет из нескольких запросов, метод ВыполнитьПакет() возвращает массив результатов. Проверять на пустоту нужно тот элемент массива, который соответствует интересующему запросу, — индексация идёт по порядку запросов в пакете, начиная с нуля. Промежуточные запросы, создающие временные таблицы, в результирующий массив также попадают, и смещение индексов — частая причина проверки «не того» результата.

Как убедиться, что проверка работает правильно

Простейший способ проверки — временно выполнить код с заведомо несуществующим условием: передать в параметр артикул, которого точно нет в базе, и убедиться, что срабатывает ветка обработки пустого результата. Затем повторить с существующим значением и проверить, что выполняется основная ветка.

Для отладки удобно вывести результат запроса в консоль запросов (в типовых конфигурациях на управляемых формах она часто доступна через подсистему разработчика, либо используется внешняя обработка консоли запросов). Там видно фактическое количество строк, которое возвращает запрос с конкретными параметрами, — часто выясняется, что запрос пуст не из-за отсутствия данных, а из-за неверно переданного параметра.

При ревью чужого кода обращайте внимание на порядок операций: проверка на пустоту должна стоять до первого обращения к полям выборки и до любой записи данных на её основе. Если проверка находится внутри цикла или после обращения к Выборка.Поле — это признак дефекта, который проявится ровно в тот момент, когда запрос впервые вернёт ноль строк.

Контрольные точки

Как проверить результат

Выполнение с несуществующим параметром
Норма

Срабатывает ветка обработки пустого результата, ошибок нет

Тревожный признак

Ошибка обращения к полю выборки или молчаливая запись пустых данных

Выполнение с существующим параметром
Норма

Обрабатываются все строки, включая первую

Тревожный признак

Первая строка пропущена — признак лишнего вызова Следующий() перед циклом

Запрос с агрегатной функцией без данных
Норма

Значение NULL корректно обработано через ЕСТЬNULL()

Тревожный признак

Код опирается на Пустой(), который вернул Ложь при одной строке с NULL

Время выполнения проверки наличия данных
Норма

Используется ПЕРВЫЕ 1 или НайтиПоКоду(), проверка мгновенная

Тревожный признак

Полная выборка тысяч строк ради проверки факта наличия

Частые вопросы о проверке выборки на пустоту

Чем отличаются методы Пустой() и Пустая()?

Пустой() — метод результата запроса, показывает, что запрос не вернул ни одной строки. Пустая() — метод ссылки, показывает, что ссылка не указывает ни на один объект базы (пустая ссылка). Это методы разных объектов, и заменять один другим нельзя: у выборки нет метода Пустой(), а у результата запроса нет метода Пустая().

Почему Пустой() возвращает Ложь, хотя данных нет?

Чаще всего это запрос с агрегатными функциями без группировки: СУММА, КОЛИЧЕСТВО, МАКСИМУМ возвращают одну строку со значением NULL, даже когда исходных данных нет. Формально строка есть, поэтому результат не пустой. Оборачивайте агрегаты в ЕСТЬNULL() в тексте запроса и проверяйте само значение.

Что быстрее: Пустой() или Количество() = 0?

Метод Пустой() у результата запроса быстрее и экономнее: он не требует материализации данных в памяти. Количество() применяется к уже выгруженной таблице значений, то есть весь результат к этому моменту загружен в память. Если таблица нужна по другим причинам, разницы нет; если нужна только проверка — используйте Пустой().

Можно ли проверить выборку, не теряя первую строку?

Да, двумя способами. Первый — проверить РезультатЗапроса.Пустой() до получения выборки, тогда цикл обойдёт все строки. Второй — если выборка уже получена, обработать первую строку прямо внутри конструкции Если Выборка.Следующий() Тогда, а остальные — последующим циклом в той же ветке.

Как проверить, есть ли записи в регистре сведений, без запроса?

Для регистра сведений можно создать набор записей с отбором, вызвать Прочитать() и проверить Количество() набора. Однако для простой проверки факта наличия обычно эффективнее запрос с ПЕРВЫЕ 1 — он не читает все подходящие записи, а останавливается на первой найденной.

Нужна ли проверка на пустоту, если дальше обычный цикл?

Если дальше только цикл Пока Выборка.Следующий() Цикл и никакой логики вне его, формально проверка не нужна — цикл просто не выполнится. Но проверка обязательна, если по факту пустоты требуется отдельная реакция: сообщение пользователю, запись в журнал, альтернативный алгоритм или запрет записи документа.

Итог

Что важно запомнить

Проверяйте РезультатЗапроса.Пустой() до получения выборки — это универсальный и быстрый способ. Для одиночной строки используйте первый вызов Следующий(), для таблицы значений — Количество() = 0. Помните про ловушку агрегатных запросов с NULL и никогда не обращайтесь к полям выборки до проверки. Тестируйте обе ветки: с существующими и с отсутствующими данными.