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