К статье
Практический материал

Разработка и Конфигурация · 10 мин

Как в запросе 1С проверить тип регистратора

Разбираем способы проверки типа регистратора в запросе 1С: ТИПЗНАЧЕНИЯ, ТИП, ССЫЛКА, условия ВЫБОР, примеры кода, ограничения и типичные ошибки разработчика.

Регистратор — это документ, который сформировал движения по регистру. В запросах к физическим таблицам регистров накопления, сведений и расчёта поле «Регистратор» имеет составной тип: в нём может лежать ссылка на любой документ, указанный в свойствах регистра как регистратор. Поэтому задача «проверить тип регистратора» возникает постоянно: при отборах движений конкретного документа, при построении отчётов, при объединении данных из разных регистров.

В языке запросов 1С для работы с типами предусмотрены три основных инструмента: функция ТИПЗНАЧЕНИЯ(), оператор сравнения ССЫЛКА и литерал ТИП(). Каждый из них решает свою задачу и имеет ограничения. Ниже разобраны рабочие конструкции с примерами кода, типичные ошибки и способы проверить результат.

Что такое регистратор и почему его тип нужно проверять

Поле «Регистратор» присутствует в таблицах регистров, подчинённых регистратору: накопления, сведений, бухгалтерии, расчёта. Его тип — составной, то есть в одном поле могут храниться ссылки на документы разных видов: «Поступление товаров и услуг», «Реализация товаров и услуг», «Списание товаров» и так далее.

Проверка типа нужна в нескольких типовых ситуациях:

  • отобрать движения, сделанные только определённым видом документов;
  • вывести разные реквизиты документа в зависимости от его вида (у разных документов разные поля);
  • исключить из отчёта служебные документы, например «Корректировку регистров»;
  • сгруппировать данные по виду документа-регистратора.

Функция ТИПЗНАЧЕНИЯ — основной способ проверки

Функция ТИПЗНАЧЕНИЯ() возвращает тип значения, переданного в параметре. Результат сравнивается с литералом ТИП(), в котором указывается конкретный тип данных. Для ссылочных типов синтаксис выглядит так: ТИП(Документ.ИмяДокумента).

Пример запроса, который выбирает движения только по документам «Реализация товаров и услуг»:

ВЫБРАТЬ

ТоварыНаСкладах.Регистратор КАК Регистратор,

ТоварыНаСкладах.Номенклатура КАК Номенклатура,

ТоварыНаСкладах.Количество КАК Количество

ИЗ

РегистрНакопления.ТоварыНаСкладах КАК ТоварыНаСкладах

ГДЕ

ТИПЗНАЧЕНИЯ(ТоварыНаСкладах.Регистратор) = ТИП(Документ.РеализацияТоваровУслуг)

Обратите внимание: имя документа в ТИП() пишется без пробелов — так, как оно задано в конфигураторе, а не синоним. Если имя указано с ошибкой, запрос не выполнится, и конструктор запросов выдаст сообщение о неверном типе.

Ту же функцию можно использовать в списке выбираемых полей, чтобы вывести тип регистратора как отдельную колонку. В результате запроса значение будет иметь тип «Тип», что удобно для отладки, но не для вывода пользователю — для представления лучше выводить сам регистратор.

Оператор ССЫЛКА — короткая проверка в условии ГДЕ

Для отбора по типу ссылки в языке запросов есть специальный оператор ССЫЛКА. Он проверяет, является ли значение ссылкой на объект указанного вида, и часто читается проще, чем ТИПЗНАЧЕНИЯ:

ВЫБРАТЬ

ТоварыНаСкладах.Регистратор КАК Регистратор,

СУММА(ТоварыНаСкладах.Количество) КАК Количество

ИЗ

РегистрНакопления.ТоварыНаСкладах КАК ТоварыНаСкладах

ГДЕ

ТоварыНаСкладах.Регистратор ССЫЛКА Документ.ПоступлениеТоваровУслуг

СГРУППИРОВАТЬ ПО

ТоварыНаСкладах.Регистратор

По сути, для ссылочных значений Регистратор ССЫЛКА Документ.Имя и ТИПЗНАЧЕНИЯ(Регистратор) = ТИП(Документ.Имя) дают одинаковый результат. Разница в удобстве чтения и в том, что ССЫЛКА применима только к ссылочным типам, а ТИПЗНАЧЕНИЯ работает и с примитивными типами (число, строка, дата).

Сравнение способов проверки типа

ТИПЗНАЧЕНИЯ = ТИП()

Универсальный способ, работает с любыми типами, подходит для ВЫБОР КОГДА и вычисляемых полей. Запись длиннее.

Оператор ССЫЛКА

Короткая и наглядная проверка в условии ГДЕ. Применим только к ссылочным типам.

ВЫРАЗИТЬ(Регистратор КАК Документ.Имя)

Приведение типа: даёт доступ к реквизитам конкретного документа. Если тип не совпадает, результат — NULL.

Конструкция ВЫБОР КОГДА для разных типов регистратора

Когда по одному регистру движения делают несколько видов документов и нужно вывести разные данные в зависимости от вида, применяется конструкция ВЫБОР КОГДА ... ТОГДА ... КОНЕЦ:

ВЫБРАТЬ

Взаиморасчеты.Регистратор КАК Регистратор,

ВЫБОР

КОГДА Взаиморасчеты.Регистратор ССЫЛКА Документ.ПоступлениеТоваровУслуг

ТОГДА ВЫРАЗИТЬ(Взаиморасчеты.Регистратор КАК Документ.ПоступлениеТоваровУслуг).ДоговорКонтрагента

КОГДА Взаиморасчеты.Регистратор ССЫЛКА Документ.РеализацияТоваровУслуг

ТОГДА ВЫРАЗИТЬ(Взаиморасчеты.Регистратор КАК Документ.РеализацияТоваровУслуг).ДоговорКонтрагента

ИНАЧЕ NULL

КОНЕЦ КАК Договор

ИЗ

РегистрНакопления.ВзаиморасчетыСКонтрагентами КАК Взаиморасчеты

Здесь ключевой приём — оператор ВЫРАЗИТЬ(). Через точку от поля составного типа нельзя обратиться к реквизиту, которого нет у всех возможных видов документов. ВЫРАЗИТЬ приводит значение к конкретному типу документа, после чего его реквизиты доступны. Если фактический тип не совпадает, результат приведения — NULL, поэтому приведение безопасно сочетать с проверкой типа в ВЫБОР.

Группировка и отчёты по видам регистраторов

Если нужно построить сводку по видам документов, сделавших движения, функцию ТИПЗНАЧЕНИЯ помещают в группировку:

ВЫБРАТЬ

ТИПЗНАЧЕНИЯ(Движения.Регистратор) КАК ТипДокумента,

КОЛИЧЕСТВО(РАЗЛИЧНЫЕ Движения.Регистратор) КАК КоличествоДокументов,

СУММА(Движения.Количество) КАК ВсегоДвижений

ИЗ

РегистрНакопления.ТоварыНаСкладах КАК Движения

СГРУППИРОВАТЬ ПО

ТИПЗНАЧЕНИЯ(Движения.Регистратор)

Такой запрос быстро показывает, какие виды документов реально формируют движения по регистру, — это полезно при отладке и при анализе чужой конфигурации. В СКД (системе компоновки данных) аналогичный приём используют для вычисляемых полей и отборов по виду документа.

Перед тем как писать сложный запрос с ВЫБОР КОГДА, выполните простой запрос с группировкой по ТИПЗНАЧЕНИЯ(Регистратор) на реальных данных. Часто выясняется, что по регистру движения делают не те документы, которые ожидались, или есть «мусорные» регистраторы вроде корректировок.
ПЗ
Практическое замечание

Ограничения и производительность

Проверка типа через ТИПЗНАЧЕНИЯ или ССЫЛКА не использует индексы эффективно: СУБД приходится вычислять тип для каждой строки. На больших таблицах регистров условие по типу регистратора может заметно замедлить запрос. По возможности сочетайте его с другими отборами — по периоду, по измерениям регистра, — которые сокращают объём обрабатываемых записей.

Ещё одно ограничение: в литерале ТИП() и после оператора ССЫЛКА нельзя подставить параметр — вид документа должен быть указан явно в тексте запроса. Если вид документа должен выбираться пользователем, придётся формировать текст запроса программно или использовать несколько условий через ИЛИ с отключением ненужных веток через параметры.

Также помните, что в виртуальных таблицах регистров (Остатки, Обороты) поля «Регистратор» нет — оно есть только в физической таблице движений и в таблице «Обороты» с детализацией до регистратора. Проверять тип регистратора в таблице остатков бессмысленно.

Типичные ошибки
01
Использование синонима документа вместо имени в ТИП(Документ.Имя) — запрос не выполняется с ошибкой типа.
02
Обращение к реквизиту регистратора через точку без ВЫРАЗИТЬ — ошибка «Поле не найдено», если реквизит есть не у всех видов документов.
03
Попытка отобрать по типу регистратора в виртуальной таблице Остатки — поля Регистратор там нет.
04
Сравнение ТИПЗНАЧЕНИЯ со строкой вместо литерала ТИП() — условие никогда не выполняется.

Как проверить результат запроса

После написания запроса проверьте его на реальных данных в консоли запросов. Контрольные точки:

  • запрос выполняется без ошибок компиляции — значит, имена типов и поля указаны верно;
  • в результате присутствуют только регистраторы ожидаемого вида — откройте несколько ссылок и убедитесь визуально;
  • если использовался ВЫБОР КОГДА с ИНАЧЕ NULL — проверьте, есть ли строки с NULL: они показывают регистраторы неучтённых видов;
  • сравните количество записей с отбором и без него — слишком маленькое число может означать ошибку в имени типа.
Контрольные точки

Как проверить результат

Выполнение запроса
Норма

Запрос выполняется без сообщений об ошибках в консоли запросов

Тревожный признак

Ошибка «Ошибка в выражении» или «Поле не найдено» — проверьте имя документа и ВЫРАЗИТЬ

Содержимое результата
Норма

Все регистраторы в выборке принадлежат нужному виду документов

Тревожный признак

Попадаются документы других видов или пустой результат при заведомо существующих движениях

Поля из ВЫБОР КОГДА
Норма

Для каждого вида регистратора выведены корректные значения

Тревожный признак

Много NULL — значит, есть виды регистраторов, не учтённые в ветках КОГДА

Итог

Что важно запомнить

Тип регистратора проверяется через ТИПЗНАЧЕНИЯ(Регистратор) = ТИП(Документ.Имя) или оператором Регистратор ССЫЛКА Документ.Имя. Для доступа к реквизитам конкретного документа используйте ВЫРАЗИТЬ внутри ВЫБОР КОГДА. Поле Регистратор есть только в физических таблицах движений, а проверка типа не использует индексы — дополняйте её другими отборами.

Частые вопросы

Можно ли передать вид документа в запрос параметром?

Нет, в литерале ТИП() и после оператора ССЫЛКА параметр использовать нельзя — вид документа указывается явно в тексте. Обходные пути: программная подстановка имени в текст запроса или набор условий через ИЛИ с параметрами-флагами, включающими нужные ветки.

Чем ТИПЗНАЧЕНИЯ отличается от ССЫЛКА?

ТИПЗНАЧЕНИЯ возвращает тип любого значения и сравнивается с ТИП() — работает и с примитивными типами. ССЫЛКА — специальный оператор проверки только для ссылочных типов, запись короче. Для регистратора оба способа дают одинаковый результат.

Почему запрос падает с ошибкой «Поле не найдено» при обращении к реквизиту регистратора?

Потому что поле Регистратор имеет составной тип, а запрошенный реквизит есть не у всех видов документов-регистраторов. Решение — привести значение через ВЫРАЗИТЬ(Регистратор КАК Документ.Имя) и только потом обращаться к реквизиту.

Можно ли проверить тип регистратора в виртуальной таблице Остатки?

Нет, в виртуальных таблицах Остатки и Обороты (без детализации) поля Регистратор нет. Проверка типа возможна только в физической таблице регистра или в таблице Обороты с указанием периодичности «Регистратор».

Как исключить из отчёта движения документа «Корректировка регистров»?

Добавьте в условие ГДЕ отрицание: НЕ Регистратор ССЫЛКА Документ.КорректировкаРегистров. Альтернатива — сравнение ТИПЗНАЧЕНИЯ(Регистратор) <> ТИП(Документ.КорректировкаРегистров).

Влияет ли проверка типа на скорость запроса?

Да, условие по типу вычисляется для каждой строки и не использует индексы. На больших регистрах сочетайте проверку типа с отборами по периоду и измерениям, чтобы сократить объём обрабатываемых записей.