Как программно проверить наличие документа в базе 1С?

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

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

Ошибочный подход: использование объектной выборки

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


ТипДокумента = Объект.Имя;
ВыборДок = Документы[ТипДокумента].Выбрать();
Пока ВыборДок.Следующий() Цикл
    Если ЗначениеЗаполнено(ВыборДок.Ссылка) Тогда
        Сообщить(Объект);
        Прервать; // Достаточно найти один
    КонецЕсли;
КонецЦикла;

Проанализируем этот код. Таким образом мы действительно проверяем наличие любого документа выбранного типа. Однако, если документов в базе много (сотни тысяч или миллионы), процесс может сильно затянуться по времени. Метод Выбрать вытягивает данные в оперативную память сервера небольшими порциями, что крайне неэффективно для простой проверки существования записей.

Оптимальное решение 1: Запрос к таблице документа

Самым правильным и ресурсосберегающим подходом является использование языка запросов. Нам достаточно запросить всего одну запись из таблицы. Если результат не пустой, значит, документы в базе есть. Рассмотрим подробнее, как составить такой динамический запрос:


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

// Динамически подставляем имя таблицы
Запрос.Текст = СтрЗаменить(Запрос.Текст, "&Таблица", ОбъектМетаданных.ПолноеИмя());

Результат = Запрос.Выполнить();
Если НЕ Результат.Пустой() Тогда
    // Значит документы этого типа есть в базе
КонецЕсли;

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

Оптимальное решение 2: Запрос к регистру

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


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

Запрос.УстановитьПараметр("ТипДокумента", Тип("ДокументСсылка." + ОбъектМетаданных.Имя));

Результат = Запрос.Выполнить();
Если НЕ Результат.Пустой() Тогда
    // Документ делает движения и присутствует в базе
КонецЕсли;

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

Использование функций Библиотеки стандартных подсистем (БСП)

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


ИмяТаблицы = "Документ." + ОбъектМетаданных.Имя;
ТаблицаПустая = ОбщегоНазначения.ТаблицаПустая(ИмяТаблицы);

Если НЕ ТаблицаПустая Тогда
    // В таблице есть хотя бы один документ
КонецЕсли;

Эта функция сама формирует безопасный запрос с конструкцией ПЕРВЫЕ 1 и возвращает булево значение. Ее использование делает код более читаемым и надежным.

Важный нюанс: Учет прав доступа (RLS)

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

Если нам необходимо проверить 100% физическое наличие документа в базе данных независимо от прав текущего пользователя, проверку необходимо оборачивать в привилегированный режим. Разберем этот момент на примере:


УстановитьПривилегированныйРежим(Истина);

// Выполняем проверку через БСП или запрос
ИмяТаблицы = "Документ." + ОбъектМетаданных.Имя;
ТаблицаПустая = ОбщегоНазначения.ТаблицаПустая(ИмяТаблицы);

УстановитьПривилегированныйРежим(Ложь);

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

← На главную