Как узнать количество элементов в справочнике 1С или проверить, пустой ли он?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

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

Разберем наиболее эффективные, проверенные и стандартизированные способы решения этих задач средствами языка запросов и объектной модели 1С.

Способ 1. Быстрая проверка справочника на пустоту через запрос

Если перед нами стоит задача только узнать, пуст справочник или в нем уже есть данные, нам не требуется пересчитывать все записи таблицы. Достаточно запросить у СУБД ровно одну любую запись с помощью конструкции ВЫБРАТЬ ПЕРВЫЕ 1 и проверить результат выполнения методом Пустой().

Посмотрим на классический пример такого запроса:


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ ПЕРВЫЕ 1
    |	1 КАК ПолеКонстанта
    |ИЗ
    |	Справочник.Номенклатура КАК Номенклатура";

РезультатЗапроса = Запрос.Выполнить();
СправочникПуст = РезультатЗапроса.Пустой();

Если СправочникПуст Тогда
    // Действия, если данных нет
КонецЕсли;

Обратим внимание на выборку константы 1 вместо реальных реквизитов или ссылок: серверу не приходится тратить время на чтение строк переменной длины или разыменование полей, он возвращает фиктивное значение при обнаружении первой же физической строки в таблице.

Способ 2. Подсчет точного количества элементов

Когда требуется выяснить точное количество элементов, хранящихся в справочнике, оптимальным вариантом является применение агрегатной функции КОЛИЧЕСТВО(*). СУБД выполняет подсчет на уровне движка базы данных и передает на сторону 1С только одно итоговое число.

Рассмотрим пример кода:


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |	КОЛИЧЕСТВО(*) КАК ВсегоЭлементов
    |ИЗ
    |	Справочник.Номенклатура КАК Номенклатура";

Выборка = Запрос.Выполнить().Выбрать();
Если Выборка.Следующий() Тогда
    ВсегоЭлементов = Выборка.ВсегоЭлементов;
КонецЕсли;

В среде разработчиков часто возникает вопрос: есть ли разница в производительности между КОЛИЧЕСТВО(*) и КОЛИЧЕСТВО(Ссылка)? Разберем этот момент подробнее:

  1. Поле Ссылка является первичным ключом таблицы и входит в кластерный индекс базы данных.
  2. Значение поля Ссылка никогда не может быть равным NULL.
  3. Стандартная функция COUNT(*) подсчитывает все строки, включая содержащие NULL, а COUNT(Выражение) игнорирует строки со значением NULL. Поскольку ссылка всегда заполнена, оптимизатор СУБД генерирует абсолютно идентичный план выполнения для обоих вариантов. Тем не менее общепринятым стандартом 1С для подсчета всех строк является именно КОЛИЧЕСТВО(*).

Важное замечание: согласно стандартам разработки платформы 1С, категорически запрещено заменять функцию КОЛИЧЕСТВО(*) конструкцией СУММА(1). На таблицах больших объемов (от 10 млн строк) суммирование единиц вызывает ошибку арифметического переполнения из-за фиксированной разрядности промежуточных вычислений в СУБД.

Способ 3. Проверка на пустоту через объектную модель

Иногда требуется проверить наличие записей без составления текста запроса, оперируя исключительно менеджером справочника. В таком случае крайне не рекомендуется использовать перебор выборки в цикле. Достаточно прочитать первую запись:


Выборка = Справочники.Номенклатура.Выбрать();
СправочникПуст = НЕ Выборка.Следующий();

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

Практические нюансы, влияющие на результат

При проверке справочников важно учитывать условия реальной конфигурации, которые могут исказить итоговые цифры:

  1. Ограничения доступа на уровне записей (RLS): если у пользователя ограничены права на просмотр конкретных строк справочника, обычный запрос вернет признак пустоты или заниженное количество, даже если данные в таблице есть. Если нам требуется проверить физическое наличие записей на уровне всей информационной базы, выполнение кода следует переносить в привилегированный режим с помощью директивы УстановитьПривилегированныйРежим(Истина).
  2. Предопределенные элементы: справочник может содержать предопределенные строки, добавленные разработчиком в конфигураторе. База данных физически не пуста, но пользовательские данные могут отсутствовать. Чтобы исключить системные элементы, используем отбор:
    
    ГДЕ
    	Номенклатура.Предопределенный = ЛОЖЬ
    
  3. Помеченные на удаление и группы: в запросы без фильтрации попадают также удаленные элементы и группы иерархии. Если задача состоит в подсчете только актуальных позиций, в секцию ГДЕ необходимо добавить условия ПометкаУдаления = ЛОЖЬ и ЭтоГруппа = ЛОЖЬ (для иерархических справочников).
  4. Разделение данных (режим SaaS): в разделенных конфигурациях проверка всегда выполняется в контексте текущей области данных. Записи других абонентов, хранящиеся в этой же таблице СУБД, отсекаются платформой автоматически.
← На главную