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