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

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

Как в запросе 1С проверить тип объекта

Как в запросе 1С проверить тип объекта: функция ТИПЗНАЧЕНИЯ, оператор ССЫЛКА, сравнение с ТИП, приведение ВЫРАЗИТЬ. Примеры кода, ошибки и FAQ.

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

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

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

Функция ТИПЗНАЧЕНИЯ: получить тип поля в запросе

Функция ТИПЗНАЧЕНИЯ() возвращает тип значения переданного выражения. Результат можно сравнить с конкретным типом через литерал ТИП(), поместить в поле выборки или использовать в условиях ВЫБОР.

ВЫБРАТЬ

ТИПЗНАЧЕНИЯ(ДополнительныеСведения.Значение) КАК ТипЗначения,

ДополнительныеСведения.Значение КАК Значение

ИЗ

РегистрСведений.ДополнительныеСведения КАК ДополнительныеСведения

ГДЕ

ТИПЗНАЧЕНИЯ(ДополнительныеСведения.Значение) = ТИП(Справочник.Номенклатура)

Здесь запрос отбирает только те записи регистра, где значение дополнительного сведения является ссылкой на справочник «Номенклатура». Литерал ТИП(Справочник.Номенклатура) задаёт тип через имя метаданного — точно так же, как оно указано в дереве конфигурации.

Функцию можно выводить в результат запроса и затем группировать по ней или анализировать в коде. Учтите: для полей примитивных типов (строка, число, дата) ТИПЗНАЧЕНИЯ вернёт соответствующий примитивный тип, а для значений NULL — тип NULL, что удобно для проверки незаполненных составных полей.

Оператор ССЫЛКА: быстрая проверка ссылочного типа

Оператор ССЫЛКА проверяет, является ли значение поля ссылкой на указанный вид объекта. Синтаксически это самая короткая и читаемая конструкция для фильтрации:

ВЫБРАТЬ

ХозрасчетныйСубконто.Значение КАК Значение

ИЗ

РегистрБухгалтерии.Хозрасчетный.Субконто КАК ХозрасчетныйСубконто

ГДЕ

ХозрасчетныйСубконто.Значение ССЫЛКА Справочник.Контрагенты

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

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

Сравнение подходов

ССЫЛКА

Короткая проверка ссылочного типа в условии ГДЕ. Не работает с примитивными типами и не выводится в результат.

ТИПЗНАЧЕНИЯ + ТИП

Универсальный вариант: работает со ссылками и примитивами, результат можно выводить и группировать. Чуть более громоздкий синтаксис.

ВЫРАЗИТЬ

Не проверка, а приведение типа: позволяет обратиться к реквизитам составного поля и ускорить соединения.

Литерал ТИП: как задать тип для сравнения

Литерал ТИП() принимает в качестве параметра имя типа и возвращает значение типа «Тип». Формат: ТИП(Справочник.Номенклатура), ТИП(Документ.ПоступлениеТоваровУслуг), ТИП(Перечисление.СтавкиНДС).

Для примитивных типов синтаксис другой — используются ключевые слова СТРОКА, ЧИСЛО, ДАТА, БУЛЕВО:

ВЫБОР

КОГДА ТИПЗНАЧЕНИЯ(ЗначенияСвойств.Значение) = ТИП(СТРОКА)

ТОГДА "Текст"

КОГДА ТИПЗНАЧЕНИЯ(ЗначенияСвойств.Значение) = ТИП(ЧИСЛО)

ТОГДА "Число"

КОГДА ТИПЗНАЧЕНИЯ(ЗначенияСвойств.Значение) = ТИП(БУЛЕВО)

ТОГДА "Флаг"

ИНАЧЕ "Ссылка"

КОНЕЦ КАК ВидЗначения

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

ВЫРАЗИТЬ: приведение составного поля к конкретному типу

Оператор ВЫРАЗИТЬ() не проверяет тип, а приводит значение к указанному типу. Основное применение — обращение к реквизитам составного ссылочного поля. Если поле может хранить ссылки на разные справочники, прямое обращение к реквизиту Наименование вернёт данные не для всех записей; после приведения запрос будет трактовать поле как ссылку на конкретный объект:

ВЫБРАТЬ

ВЫРАЗИТЬ(Субконто.Значение КАК Справочник.Номенклатура).Код КАК КодНоменклатуры,

ВЫРАЗИТЬ(Субконто.Значение КАК Справочник.Номенклатура).Артикул КАК Артикул

ИЗ

РегистрБухгалтерии.Хозрасчетный.Субконто КАК Субконто

ГДЕ

Субконто.Значение ССЫЛКА Справочник.Номенклатура

Для записей, где значение не является номенклатурой, приведённые поля вернут NULL, поэтому приведение почти всегда сочетают с условием ССЫЛКА или ТИПЗНАЧЕНИЯ.

Второе применение ВЫРАЗИТЬ — оптимизация соединений. Когда составное поле участвует в соединении таблиц, платформа строит соединение со всеми возможными таблицами составного типа, что резко замедляет запрос. Приведение поля к одному типу до соединения сужает выборку до одной таблицы и ускоряет выполнение в разы на больших объёмах.

Проверка типа в коде встроенного языка

Когда данные уже получены из запроса, тип проверяется средствами встроенного языка. Для этого есть две функции: ТипЗнч() возвращает тип значения, а Тип() создаёт значение типа по имени:

Если ТипЗнч(СтрокаВыборки.Значение) = Тип("СправочникСсылка.Номенклатура") Тогда

// обработка ссылки на номенклатуру

КонецЕсли;

Обратите внимание на различие в именовании: в запросе пишется ТИП(Справочник.Номенклатура), а в коде — Тип("СправочникСсылка.Номенклатура"). Для ссылочных типов в коде к имени добавляется слово «Ссылка»: ДокументСсылка.РеализацияТоваровУслуг, ПеречислениеСсылка.СтавкиНДС.

Альтернатива без строкового литерала — сравнение через менеджер объекта:

Если ТипЗнч(Значение) = ТипЗнч(Справочники.Номенклатура.ПустаяСсылка()) Тогда

// значение — ссылка на номенклатуру

КонецЕсли;

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

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

Типичные ошибки при проверке типа

Первая распространённая ошибка — попытка сравнить поле с типом через обычное равенство: ГДЕ Поле = ТИП(Справочник.Номенклатура). Так запрос сравнивает значение поля со значением типа «Тип», что логически неверно. Тип проверяется только через ТИПЗНАЧЕНИЯ(Поле) или Поле ССЫЛКА.

Вторая ошибка — обращение к реквизитам составного поля без приведения. Запрос Субконто.Значение.Артикул для поля составного типа либо вернёт NULL для части записей, либо сработает неочевидным образом. Всегда оборачивайте такое поле в ВЫРАЗИТЬ.

Третья ошибка — игнорирование NULL. В левых соединениях и при незаполненных составных полях значение равно NULL, и его тип — тоже NULL. Условие ТИПЗНАЧЕНИЯ(Поле) = ТИП(...) для таких строк вернёт ложь, что обычно и требуется, но если нужно отдельно обработать пустые значения, добавьте проверку Поле ЕСТЬ NULL или ЕСТЬNULL().

Типичные ошибки
01
Сравнение Поле = ТИП(...) вместо ТИПЗНАЧЕНИЯ(Поле) = ТИП(...) — условие никогда не сработает корректно
02
Обращение к реквизитам составного поля без ВЫРАЗИТЬ — NULL вместо данных
03
Соединение по составному полю без приведения типа — резкое падение производительности
04
Использование в коде Тип("Справочник.Номенклатура") вместо Тип("СправочникСсылка.Номенклатура") — типы не совпадут
05
Опечатка в имени метаданного внутри ТИП() — ошибка компиляции запроса

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

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

Для оценки скорости выполнения используйте замер производительности в конфигураторе или консоль кода. Если запрос с проверкой типа выполняется медленно, первым делом проверьте, нет ли соединений по составным полям без ВЫРАЗИТЬ, и нет ли обращений к реквизитам через точку от составного поля — обе ситуации приводят к неявным соединениям со множеством таблиц.

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

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

Отбор по типу
Норма

В выборке только записи нужного вида объекта

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

Попадают записи других типов или выборка пуста при наличии данных

Реквизиты через ВЫРАЗИТЬ
Норма

Поля заполнены для записей целевого типа

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

Все значения NULL — вероятно, приведён не тот тип

Время выполнения
Норма

Запрос отрабатывает за секунды на рабочей базе

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

Многоминутное выполнение — проверьте соединения по составным полям

Итог

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

Тип в запросе проверяют ТИПЗНАЧЕНИЯ(Поле) = ТИП(Вид.Имя) или оператором Поле ССЫЛКА Вид.Имя. Для доступа к реквизитам составного поля и ускорения соединений используйте ВЫРАЗИТЬ. В коде встроенного языка применяйте ТипЗнч() и Тип() с именем вида «СправочникСсылка.Имя».

Частые вопросы

Чем отличается ССЫЛКА от ТИПЗНАЧЕНИЯ?

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

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

Незаполненное составное поле обычно содержит NULL. Используйте условие Поле ЕСТЬ NULL или функцию ЕСТЬNULL(Поле, ЗначениеПоУмолчанию). Проверка ТИПЗНАЧЕНИЯ(Поле) = ТИП(NULL) также допустима, но менее читаема.

Можно ли проверить тип перечисления в запросе?

Да. Синтаксис аналогичен: ТИПЗНАЧЕНИЯ(Поле) = ТИП(Перечисление.СтавкиНДС) или Поле ССЫЛКА Перечисление.СтавкиНДС. Перечисления в языке запросов считаются ссылочными типами.

Почему ВЫРАЗИТЬ возвращает NULL для части записей?

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

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

Функцией ТипЗнч(Значение) в сочетании с Тип("СправочникСсылка.ИмяОбъекта"). Не забудьте добавить слово «Ссылка» к виду объекта: Тип("ДокументСсылка.РеализацияТоваровУслуг"). Вариант через сравнение с ТипЗнч(Менеджер.ПустаяСсылка()) устойчив к опечаткам.

Влияет ли проверка типа на скорость запроса?

Сама проверка через ССЫЛКА или ТИПЗНАЧЕНИЯ практически не влияет. Медленными делают запрос соединения по составным полям и обращения к реквизитам через точку без приведения типа. Решение — ВЫРАЗИТЬ перед соединением.