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