Разработка и Конфигурация · 10 мин
Как сравнить тип в запросе 1С: рабочие способы и примеры
Способы сравнения типа в запросе 1С: функция ТИПЗНАЧЕНИЯ, оператор ССЫЛКА, проверка составных типов, приведение через ВЫРАЗИТЬ. Примеры кода и типичные ошибки.
Сравнение типа значения — частая задача при написании запросов в 1С: нужно отобрать документы определённого вида, отфильтровать записи регистра по типу регистратора или разделить строки с составным типом поля. Язык запросов 1С не имеет привычного оператора сравнения типов напрямую, но предлагает несколько штатных механизмов: функцию ТИПЗНАЧЕНИЯ(), оператор ССЫЛКА и конструкцию ВЫРАЗИТЬ().
Каждый из этих способов решает свою задачу и имеет ограничения. Неправильный выбор приводит либо к ошибке выполнения запроса, либо к тонким дефектам: например, условие молча отсекает часть данных, потому что сравнение идёт не с тем представлением типа. Ниже разобраны все рабочие варианты с примерами кода и критериями выбора.
Материал ориентирован на разработчиков и внедренцев, работающих с консолью запросов, СКД и программным построением запросов в конфигурациях на управляемых и обычных формах.
Функция ТИПЗНАЧЕНИЯ: универсальный способ сравнения типа
Функция ТИПЗНАЧЕНИЯ() возвращает тип значения поля. Результат сравнивается с литералом типа, который задаётся конструкцией ТИП(ИмяТипа). Это самый универсальный приём: он работает и для ссылочных, и для примитивных типов.
ВЫБРАТЬ
Хозрасчетный.Регистратор КАК Регистратор
ИЗ
РегистрБухгалтерии.Хозрасчетный КАК Хозрасчетный
ГДЕ
ТИПЗНАЧЕНИЯ(Хозрасчетный.Регистратор) = ТИП(Документ.ОперацияБух)
В этом примере отбираются только те записи регистра бухгалтерии, у которых регистратором является документ «ОперацияБух». Условие можно инвертировать через <> — тогда отберутся все записи, кроме указанного типа.
Важная особенность: ТИПЗНАЧЕНИЯ() допустимо использовать и в секции ВЫБРАТЬ, чтобы вывести тип в результат запроса, и в условиях соединения. Однако сравнивать результат функции можно только с литералом ТИП(...) — сравнение двух полей по типу напрямую в языке запросов не поддерживается.
Оператор ССЫЛКА: лаконичная проверка для ссылочных типов
Если проверяемое поле — ссылка, удобнее оператор ССЫЛКА. Он возвращает Истина, когда значение поля является ссылкой на указанный вид объекта. Синтаксис короче и читается легче:
ВЫБРАТЬ
Взаиморасчеты.Регистратор КАК Регистратор
ИЗ
РегистрНакопления.ВзаиморасчетыСКонтрагентами КАК Взаиморасчеты
ГДЕ
Взаиморасчеты.Регистратор ССЫЛКА Документ.ПоступлениеТоваровУслуг
Оператор ССЫЛКА применим только к ссылочным типам: документам, справочникам, планам счетов, видов расчёта и т.п. Для примитивных типов (Число, Строка, Дата) он не работает — там остаётся только ТИПЗНАЧЕНИЯ().
Отрицание строится через НЕ: НЕ Поле ССЫЛКА Справочник.Номенклатура. Это удобно, когда нужно исключить один вид объектов из выборки по составному полю.
Работа с составными типами полей
Составной тип — когда поле может хранить значения разных типов: например, поле «Контрагент» со ссылками на справочники «Контрагенты» и «Организации», или поле «Регистратор» в регистре, куда пишут несколько видов документов. Именно здесь сравнение типа встречается чаще всего.
Типичный сценарий — разное поведение запроса в зависимости от типа значения. Это делается через конструкцию ВЫБОР:
ВЫБРАТЬ
ВЫБОР
КОГДА Товары.Склад ССЫЛКА Справочник.Склады
ТОГДА "Обычный склад"
КОГДА Товары.Склад ССЫЛКА Справочник.Магазины
ТОГДА "Розничная точка"
ИНАЧЕ "Не определено"
КОНЕЦ КАК ВидХранения
ИЗ
Документ.ПеремещениеТоваров.Товары КАК Товары
При проверке составного поля учитывайте значение NULL: если соединение дало пустую ссылку или поле не заполнено, сравнение типа вернёт Ложь, и строка «уйдёт» в ветку ИНАЧЕ. Поэтому ветку ИНАЧЕ стоит заполнять осознанно, а не оставлять по умолчанию.
Проверьте, что поле действительно хранит ссылку, а не примитив
Оператор ССЫЛКА выдаст ошибку
Без приведения типа запрос не скомпилируется
Добавьте отдельную обработку NULL через ЕСТЬ NULL
Приведение типа через ВЫРАЗИТЬ
Функция ВЫРАЗИТЬ() не просто проверяет тип — она приводит значение к указанному типу. Если фактический тип не совпадает, результатом будет пустая ссылка или значение по умолчанию. Это позволяет безопасно обращаться к реквизитам, которые существуют только у конкретного вида объекта:
ВЫБРАТЬ
ВЫРАЗИТЬ(Расчеты.Регистратор КАК Документ.ПоступлениеТоваровУслуг).Организация КАК Организация
ИЗ
РегистрНакопления.РасчетыСПоставщиками КАК Расчеты
ГДЕ
Расчеты.Регистратор ССЫЛКА Документ.ПоступлениеТоваровУслуг
Без приведения типа обращение Расчеты.Регистратор.Организация через точку по составному полю привело бы к ошибке либо к неявному соединению со всеми таблицами видов документов, что резко увеличивает стоимость запроса. Явное ВЫРАЗИТЬ вместе с отбором по типу — стандартный приём оптимизации.
Дополнительно ВЫРАЗИТЬ используют для усечения строк и задания точности чисел: ВЫРАЗИТЬ(Поле КАК СТРОКА(100)). Это полезно при объединении запросов, где типы колонок должны совпадать.
Сравнение типа в СКД и динамических списках
В схеме компоновки данных те же конструкции работают в тексте запроса набора данных. Дополнительно тип можно проверять в отборах СКД: пользователю доступно условие вида «Регистратор является документом такого-то вида», если в настройках поля включён соответствующий вариант сравнения.
В динамических списках с произвольным запросом условие по типу добавляется в текст запроса списка. Учитывайте, что динамический список накладывает собственные отборы, и сложные условия с ВЫБОР по типу могут конфликтовать с механизмом основной таблицы — в таких случаях проще вынести логику во временную таблицу.
При программном построении запроса из кода условие по типу формируется строкой. Следите за подстановкой имён метаданных: безопаснее получать имя через Метаданные.Документы.РеализацияТоваровУслуг.Имя, чем жёстко писать строку — при переименовании объекта запрос не сломается незаметно.
- 1Определите, какой тип хранит поле: ссылочный, примитивный или составной
- 2Для ссылочного поля напишите условие через ССЫЛКА, для примитивного — через ТИПЗНАЧЕНИЯ
- 3Если нужны реквизиты конкретного вида объекта, добавьте ВЫРАЗИТЬ и отбор по типу
- 4Проверьте запрос в консоли запросов на копии базы, включая случаи NULL и пустых ссылок
- 5Оцените время выполнения на реальном объёме данных перед переносом в рабочий код
Типичные ошибки при сравнении типов
Первая группа ошибок — синтаксические: пропущен вид объекта в ТИП(), перепутаны скобки, оператор ССЫЛКА применён к примитивному полю. Такие ошибки отлавливаются ещё в конструкторе запроса и безобидны.
Вторая группа опаснее — логические. Например, сравнение ТИПЗНАЧЕНИЯ(Поле) = ТИП(Строка) выполняется успешно, но разработчик ожидал сравнение значения, а не типа. Или условие по типу написано для поля, которое в конфигурации имеет единственный тип, — отбор бессмыслен и только усложняет запрос.
Третья группа — производительность. Условие по типу без индексирования обрабатывается перебором, а неявные соединения из-за обращения через точку к составному полю способны замедлить запрос на порядки. Проверяйте такие запросы на объёмах, близких к рабочим.
Выбор подхода под конкретную задачу
Правило выбора простое: для ссылок — ССЫЛКА, для примитивов и универсальных проверок — ТИПЗНАЧЕНИЯ(), для доступа к реквизитам — ВЫРАЗИТЬ() в связке с отбором по типу. Комбинировать их в одном запросе нормально и часто необходимо.
Если одно и то же условие по типу используется в нескольких запросах, вынесите его в пакет с временной таблицей: сначала отберите ссылки нужного вида во временную таблицу, затем соединяйтесь с ней. Это упрощает поддержку и обычно быстрее, чем повторять условие в каждом запросе пакета.
Сравнение вариантов
Универсально: ссылки и примитивы. Минус — более громоздкий синтаксис и нельзя сравнить типы двух полей между собой
Коротко и наглядно для ссылочных типов. Не работает с примитивными типами
Даёт доступ к реквизитам конкретного вида и устраняет неявные соединения. Само по себе не фильтрует — нужно условие по типу
Часто задаваемые вопросы
Можно ли сравнить типы двух полей между собой в запросе?
Напрямую — нет: конструкция вида ТИПЗНАЧЕНИЯ(Поле1) = ТИПЗНАЧЕНИЯ(Поле2) в языке запросов не поддерживается. Обходной путь — перечислить нужные комбинации через ВЫБОР с парами условий ССЫЛКА для каждого поля.
Как проверить, что поле содержит пустую ссылку определённого вида?
Сравните поле с пустой ссылкой: Поле = ЗНАЧЕНИЕ(Справочник.Номенклатура.ПустаяСсылка). Проверка типа здесь не нужна — пустая ссылка уже имеет конкретный вид объекта.
Работает ли сравнение типа в параметрах виртуальных таблиц?
Ограниченно. В параметрах виртуальных таблиц лучше использовать стандартные условия по измерениям и реквизитам, а фильтрацию по типу регистратора выполнять в основном запросе после выборки из виртуальной таблицы.
Почему условие ТИПЗНАЧЕНИЯ возвращает Ложь для заполненного поля?
Чаще всего поле содержит NULL после левого соединения, а для NULL любое сравнение типа даёт Ложь. Проверьте соединения и добавьте обработку через ЕСТЬ NULL или ЕСТЬNULL.
Что быстрее: ССЫЛКА или ТИПЗНАЧЕНИЯ?
Для ссылочных полей разница в скорости несущественна — выбирайте по читаемости. На производительность влияет не оператор, а отсутствие подходящих индексов и неявные соединения при обращении к реквизитам составных полей.
Можно ли сравнить тип в запросе к табличной части?
Да, если реквизит табличной части имеет составной тип. Синтаксис тот же: условие ССЫЛКА или ТИПЗНАЧЕНИЯ по реквизиту табличной части в секции ГДЕ либо внутри ВЫБОР.
Что важно запомнить
Сравнение типа в запросе 1С делается тремя инструментами: ТИПЗНАЧЕНИЯ для универсальных проверок, ССЫЛКА для ссылочных полей, ВЫРАЗИТЬ для доступа к реквизитам конкретного вида. Всегда указывайте полное имя типа с видом объекта, обрабатывайте NULL и проверяйте запрос на реальном объёме данных.