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

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

Как использовать перечисления в запросах 1С

Как использовать перечисления в запросах 1С: функция ЗНАЧЕНИЕ, сравнение в условиях, получение представления, типичные ошибки и проверка результата.

Перечисление в 1С — это предопределённый тип данных с фиксированным списком значений, заданным в конфигураторе: виды номенклатуры, ставки НДС, пол, виды договоров. В запросах перечисления встречаются постоянно: по ним фильтруют записи, группируют итоги, выводят понятные пользователю представления. При этом работа с ними отличается от работы со справочниками, и попытка применить привычные приёмы часто заканчивается пустой выборкой или ошибкой исполнения запроса.

Ключевое отличие в том, что значение перечисления нельзя получить через точку от ссылки на справочник или через параметр-строку. Для обращения к конкретному значению в языке запросов существует специальная функция ЗНАЧЕНИЕ, а для сравнения и представления — свои правила. Ниже разобраны все основные сценарии: от простого отбора до соединений и виртуальных таблиц.

Как сослаться на значение перечисления через ЗНАЧЕНИЕ

Функция ЗНАЧЕНИЕ — единственный способ указать литеральное значение перечисления прямо в тексте запроса. Синтаксис строгий: ЗНАЧЕНИЕ(Перечисление.ИмяПеречисления.ИмяЗначения). Имена должны совпадать с именами в конфигураторе, а не с синонимами, которые видит пользователь. Если перечисление называется СтавкиНДС, а значение — НДС20, запись будет ЗНАЧЕНИЕ(Перечисление.СтавкиНДС.НДС20).

Типичный запрос с отбором по значению перечисления выглядит так:

// Пример: отбор номенклатуры с заданным видом

ВЫБРАТЬ

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

Номенклатура.ВидНоменклатуры КАК Вид

ИЗ

Справочник.Номенклатура КАК Номенклатура

ГДЕ

Номенклатура.ВидНоменклатуры = ЗНАЧЕНИЕ(Перечисление.ВидыНоменклатуры.Услуга)

Если имя перечисления или значения указано с ошибкой, запрос не выполнится: консоль запросов или отладчик выдаст сообщение о том, что значение не найдено. Поэтому имена удобно копировать из конфигуратора или из подсказки конструктора запроса, а не набирать вручную.

Отбор по перечислению: равенство, список и параметр

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

ГДЕ

Товары.СтавкаНДС В (

ЗНАЧЕНИЕ(Перечисление.СтавкиНДС.НДС10),

ЗНАЧЕНИЕ(Перечисление.СтавкиНДС.НДС20))

Когда значение перечисления должно выбираться динамически — например, из настроек отчёта или параметров обработки, — правильнее передавать его через параметр запроса:

Запрос = Новый Запрос;

Запрос.Текст =

"ВЫБРАТЬ

| Контрагенты.Ссылка

|ИЗ

| Справочник.Контрагенты КАК Контрагенты

|ГДЕ

| Контрагенты.ЮридическоеФизическоеЛицо = &ВидКонтрагента";

Запрос.УстановитьПараметр("ВидКонтрагента",

Перечисления.ЮридическоеФизическоеЛицо.ЮридическоеЛицо);

Обратите внимание: в модуле значение получается через менеджер Перечисления.Имя.Значение, а в тексте запроса — через ЗНАЧЕНИЕ. Смешивать эти два синтаксиса нельзя: Перечисления.Имя.Значение внутри текста запроса не работает.

Способы задать значение перечисления

ЗНАЧЕНИЕ в тексте запроса

Подходит для фиксированных значений, зашитых в логику запроса. Минус: при переименовании значения в конфигураторе запрос сломается.

Параметр запроса

Подходит, когда значение выбирает пользователь или вычисляет код. Гибче и безопаснее при изменениях конфигурации, но требует установки параметра перед выполнением.

Временная таблица со значениями

Подходит для сложных отборов по спискам значений с дополнительными условиями. Избыточна для простых случаев.

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

У реквизита типа «перечисление» может быть пустое значение — если поле не заполнено. Проверка на NULL здесь не подходит: незаполненный реквизит хранит именно пустую ссылку перечисления, а не NULL. Правильная проверка — сравнение с ЗНАЧЕНИЕ без указания конкретного значения:

ГДЕ

Номенклатура.ВидНоменклатуры = ЗНАЧЕНИЕ(Перечисление.ВидыНоменклатуры.ПустаяСсылка)

Либо в обратную сторону — отбор только заполненных значений через неравенство <>. Запись ЗНАЧЕНИЕ(Перечисление.Имя.) с пустым именем значения тоже допустима и означает пустую ссылку, но вариант с явным ПустаяСсылка читается лучше.

Вывод представления и порядок значений

По умолчанию запрос возвращает ссылку на значение перечисления. При выводе в таблицу значений или СКД платформа сама подставит синоним, но если результат обрабатывается кодом или передаётся вовне, понадобится функция ПРЕДСТАВЛЕНИЕ:

ВЫБРАТЬ

Документ.Ссылка КАК Документ,

ПРЕДСТАВЛЕНИЕ(Документ.ВидОперации) КАК ВидОперацииТекстом

ИЗ

Документ.РеализацияТоваровУслуг КАК Документ

Сортировка по полю-перечислению выполняется не по алфавиту синонимов, а по порядку значений в конфигураторе. Это удобно, когда порядок осмысленный (например, стадии сделки), но неожиданно, если вы ждёте алфавитного списка. Для алфавитной сортировки упорядочивайте по ПРЕДСТАВЛЕНИЕ(Поле).

С индексом значения перечисления в языке запросов работать напрямую нельзя — функций вроде «номер значения» нет. Если порядковый номер нужен для логики, его придётся вычислять в коде через Перечисления.Имя.Индекс(Значение) уже после выполнения запроса.

Перечисления в соединениях, группировках и виртуальных таблицах

Поле-перечисление можно использовать в условии соединения таблиц так же, как любое другое поле. Например, соединить документы с регистром сведений по совпадению вида операции. Это работает, потому что платформа сравнивает значения перечислений напрямую, без разыменования.

Группировка по перечислению — стандартный приём для аналитики: посчитать количество документов по видам операций или суммы по ставкам НДС:

ВЫБРАТЬ

Продажи.СтавкаНДС КАК Ставка,

СУММА(Продажи.СуммаОборот) КАК Сумма

ИЗ

РегистрНакопления.Продажи.Обороты КАК Продажи

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

Продажи.СтавкаНДС

В параметрах виртуальных таблиц (например, отбор в Обороты регистра бухгалтерии по субконто-перечислению) значение передаётся как обычный параметр. Важно помнить: фильтрация на уровне виртуальной таблицы быстрее, чем отбор в ГДЕ основного запроса, потому что СУБД получает уже сокращённый набор данных.

Порядок написания запроса с перечислением
  1. 1
    Откройте конфигуратор и спишите точные имена перечисления и нужного значения (не синонимы).
  2. 2
    Сформулируйте текст запроса, используя ЗНАЧЕНИЕ(Перечисление.Имя.Значение) в условии ГДЕ.
  3. 3
    Если значение динамическое — замените литерал на параметр и установите его через УстановитьПараметр.
  4. 4
    Выполните запрос в консоли запросов и проверьте, что выборка не пустая и содержит ожидаемые записи.
  5. 5
    Проверьте граничные случаи: записи с пустым значением реквизита и записи с другими значениями перечисления.

Типичные ошибки и как их проверить

Самая распространённая ошибка — использование синонима вместо имени. Если в конфигураторе значение называется ФизическоеЛицо, а синоним — «Физическое лицо», то ЗНАЧЕНИЕ(Перечисление.ВидыЛиц.ФизическоеЛицо) сработает, а попытка написать синоним приведёт к ошибке исполнения.

Вторая группа ошибок — сравнение перечисления со строкой. Запрос ГДЕ СтавкаНДС = "НДС20" не упадёт с ошибкой, но вернёт пустой результат, потому что типы не совпадают. Такое молчаливое поведение опаснее явной ошибки: запрос «работает», а данных нет.

Третья типичная ситуация — перечисление переименовали в конфигурации, а запросы с жёстко зашитым ЗНАЧЕНИЕ никто не обновил. После обновления конфигурации такие запросы начинают падать. Поэтому в критичных местах предпочтительнее параметры, а после изменений метаданных полезно прогнать поиск по модулям на имя старого значения.

Типичные ошибки
01
Сравнение поля-перечисления со строкой — запрос выполняется, но возвращает пустой результат.
02
Использование синонима вместо имени значения в ЗНАЧЕНИЕ — ошибка исполнения запроса.
03
Проверка незаполненного реквизита через ЕСТЬ NULL вместо сравнения с пустой ссылкой перечисления.
04
Синтаксис менеджера Перечисления.Имя.Значение внутри текста запроса — работает только в коде, не в запросе.
05
Ожидание алфавитной сортировки — перечисления сортируются по порядку значений в конфигураторе.
Контрольные точки

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

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

Запрос выполняется без ошибок, выборка содержит записи

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

Ошибка «значение не найдено» или пустая выборка при заведомо существующих данных

Тип значения в условии
Норма

И поле, и значение в сравнении имеют тип перечисления

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

Поле сравнивается со строкой или числом

Записи с незаполненным реквизитом
Норма

Попадают в выборку при отборе по пустой ссылке

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

Исчезают из выборки при любом отборе — значит, проверка пустого значения неверна

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

Можно ли получить список всех значений перечисления запросом?

Напрямую через язык запросов — нет, у перечислений нет таблицы, которую можно выбрать. Обходные пути: перебрать значения в коде через Перечисления.Имя и метаданные, поместить их во временную таблицу и передать в запрос, либо использовать выборку из реальной таблицы данных с группировкой по полю-перечислению, если достаточно только используемых значений.

Чем ЗНАЧЕНИЕ отличается от параметра запроса?

ЗНАЧЕНИЕ — литерал, зашитый в текст запроса, его нельзя изменить без правки текста. Параметр передаётся из кода перед выполнением, что позволяет менять значение динамически и защищает запрос от переименований в конфигурации. Для отчётов и обработок с настройками почти всегда правильнее параметр.

Работает ли ЗНАЧЕНИЕ в СКД и динамических списках?

Да, функция ЗНАЧЕНИЕ доступна в тексте запроса схемы компоновки данных и в произвольных запросах динамических списков. В отборах СКД значение перечисления обычно удобнее задавать через параметры или настройки отбора — тогда пользователь сможет менять его без правки схемы.

Как сравнить два поля-перечисления разных типов?

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

Почему запрос с перечислением работает медленно?

Само по себе перечисление не замедляет запрос — это компактный тип. Медленная работа обычно связана с отбором по неиндексированному полю, использованием ПРЕДСТАВЛЕНИЕ в условиях (функция блокирует использование индекса) или соединением по полю-перечислению без подходящего индекса. Проверьте план запроса и индексирование реквизита в конфигураторе.

Итог

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

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