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