Как правильно определить тип документа в запросе 1С и избежать ошибки несоответствия типов

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

При разработке отчетов и запросов в системе 1С:Предприятие 8 программисты часто сталкиваются с необходимостью логического ветвления в зависимости от типа документа. Особенно это актуально для поля Регистратор, которое имеет составной тип данных. Ошибка «Несоответствие типов» в конструкции ВЫБОР КОГДА... — классическая ситуация, возникающая из-за неправильного сравнения ссылки на объект с описанием его типа. В этой статье мы подробно разберем, как корректно проверять типы данных, проанализируем производительность различных методов и выясним, почему некоторые привычные подходы могут замедлить работу системы.

Причина возникновения ошибки «Несоответствие типов»

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

Для решения этой задачи в языке запросов предусмотрены специальные операторы и функции. Разберем их по порядку, двигаясь от наиболее эффективных к менее предпочтительным.

Способ №1: Использование оператора ССЫЛКА

Это самый правильный и быстрый способ проверки типа в запросе. Рассмотрим синтаксис на примере из обсуждения:


ВЫБОР
    КОГДА СотрудникиОсвободившиеСтавкиВОрганизациях.Регистратор ССЫЛКА Документ.ВозвратНаРаботуОрганизаций
        ТОГДА 1
    ИНАЧЕ -1
КОНЕЦ

Почему стоит использовать именно этот метод?

  1. Производительность: На уровне СУБД этот запрос транслируется в максимально простую операцию. Платформа 1С проверяет идентификатор типа, который уже хранится в таблице базы данных (поле _ReferenceTRef или аналогичное). Это не требует обращения к таблицам самих документов.
  2. Лаконичность: Код легко читается и понимается другими разработчиками.
  3. Безопасность (RLS): Оператор ССЫЛКА корректно обрабатывается механизмом ограничения прав доступа на уровне записей.

Способ №2: Функции ТИПЗНАЧЕНИЯ и ТИП

Если по каким-то причинам использование ССЫЛКА невозможно, мы можем использовать пару функций ТИПЗНАЧЕНИЯ() и ТИП(). Проанализируем пример кода:


ВЫБОР
    КОГДА ТИПЗНАЧЕНИЯ(СотрудникиОсвободившиеСтавкиВОрганизациях.Регистратор) = ТИП(Документ.ВозвратНаРаботуОрганизаций)
        ТОГДА 1
    ИНАЧЕ -1
КОНЕЦ

В данном случае функция ТИПЗНАЧЕНИЯ извлекает тип из поля Регистратор, а функция ТИП возвращает описание типа конкретного метаданного. Теперь типы операндов совпадают, и ошибка исчезнет. Однако помните, что этот метод может работать чуть медленнее оператора ССЫЛКА на больших объемах данных.

Анализируем типичную ошибку: обращение через «.Ссылка»

В сообщениях форума справедливо заметили, что конструкция Регистратор.Ссылка — это избыточность, которой стоит избегать. Выясним причину, почему так делать «фу»:

Поле Регистратор само по себе уже содержит ссылку. Когда вы пишете Регистратор.Ссылка, вы заставляете платформу выполнять LEFT JOIN (левое соединение) с таблицами всех документов, которые входят в составной тип регистратора. Если в вашей системе сотни видов документов могут быть регистраторами, запрос попытается соединиться со всеми этими таблицами. Это приводит к колоссальному падению производительности и неоправданному расходу ресурсов сервера базы данных.

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

Передача типа документа через параметры

Иногда тип документа не должен быть «зашит» в тексте запроса. Для создания универсальных механизмов мы можем передать тип как параметр. Рассмотрим, как это реализовать в коде 1С:


// В коде на встроенном языке
Запрос.УстановитьПараметр("НужныйТип", Тип("ДокументОбъект.ВозвратНаРаботуОрганизаций"));

// В тексте запроса
ГДЕ ТИПЗНАЧЕНИЯ(СотрудникиОсвободившиеСтавкиВОрганизациях.Регистратор) = &НужныйТип

Важный нюанс: оператор ССЫЛКА не поддерживает работу с параметрами. Он работает только со статическими именами метаданных, прописанными в конфигураторе. Поэтому в динамических запросах использование ТИПЗНАЧЕНИЯ() становится единственным выходом.

Работа с типами в виртуальных таблицах

Разберем особенности работы с регистрами. Если мы используем виртуальную таблицу ОстаткиИОбороты, поле Регистратор будет доступно только при условии, что периодичность запроса установлена в значение Регистратор.

Если же вы анализируете итоги по периоду (например, месяц), значение регистратора в строке может быть неопределенным или NULL. В таких случаях проверка типа всегда будет возвращать ЛОЖЬ. Всегда проверяйте настройки периодичности перед тем, как анализировать типы регистраторов.

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

Иногда в отчете нужно вывести не просто ссылку, а название вида документа (например, для группировки). Рассмотрим два способа решения этой задачи:

  1. Для пользователя: Используйте ПРЕДСТАВЛЕНИЕ(ТИПЗНАЧЕНИЯ(Регистратор)). Это вернет синоним документа на языке пользователя (например, «Реализация товаров и услуг»).
  2. Для логики: Если вам нужно программное имя метаданных, то в запросе это сделать напрямую нельзя. Рекомендуется использовать конструкцию ВЫБОР, которая сопоставляет типы с нужными вам строковыми константами.

Группировка по типам документов

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


ВЫБРАТЬ
    ТИПЗНАЧЕНИЯ(Продажи.Регистратор) КАК ТипДокумента,
    КОЛИЧЕСТВО(РАЗЛИЧНЫЕ Продажи.Регистратор) КАК Количество
ИЗ
    РегистрНакопления.Продажи КАК Продажи
СГРУППИРОВАТЬ ПО
    ТИПЗНАЧЕНИЯ(Продажи.Регистратор)

Обратите внимание: в секции СГРУППИРОВАТЬ ПО мы используем ТИПЗНАЧЕНИЯ. Оператор ССЫЛКА здесь использовать нельзя, так как он возвращает логическое значение (Истина/Ложь), а не идентификатор типа.

Подведение итогов

Проанализировав проблему, мы можем сделать следующие выводы:

Соблюдение этих простых правил позволит вам писать не только корректный, но и высокопроизводительный код, который будет стабильно работать даже в крупных информационных базах.

← На главную