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