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