Работа с типом данных Перечисление в платформе 1С:Предприятие 8.3 является фундаментальным навыком для любого разработчика. Эти объекты позволяют жестко фиксировать набор допустимых значений, исключая ошибки ввода и обеспечивая целостность данных. Однако при написании сложных алгоритмов или выборки данных часто возникает вопрос: как корректно передать значение перечисления внутрь запроса к базе данных?

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

Рассмотрим как прямые вставки значений, так и параметризированные методы, которые считаются практикой (best practice) в современной разработке. Понимание этих нюансов критично для создания производительных и надежных программных модулей.

Суть типа данных Перечисление в архитектуре 1С

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

Каждый элемент перечисления имеет уникальный идентификатор (ссылку), имя (представление) и синоним. При обращении к ним в коде важно различать эти понятия. Например, для элемента"Черновик" имя может быть Черновик, а синоним —"На согласовании".

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

⚠️ Внимание: Значения перечислений жестко привязаны к конфигурации. При обновлении типовых конфигураций разработчики могут изменять имена элементов. Код, завязанный на строковые константы, может перестать работать после обновления.

💡

Всегда используйте предопределенные имена элементов перечисления в коде, а не их текстовые представления (синонимы), так как синонимы могут быть переведены на другой язык интерфейса.

Прямое обращение к перечислению в тексте запроса

Самый простой способ использовать значение перечисления — вписать его непосредственно в текст запроса. Для этого используется специальный синтаксис, указывающий интерпретатору, что далее следует имя элемента из метаданных.

Синтаксис требует указания типа данных и имени элемента через точку. Это позволяет системе сразу резолвить (преобразовывать) значение в внутренний идентификатор GUID на этапе компиляции запроса. Такой подход удобен для статических условий, которые не меняются в runtime.

Рассмотрим пример выборки документов, у которых установлен конкретный статус. Допустим, у нас есть перечисление СтатусыДокументов с элементом Проведен.

ВЫБРАТЬ

РеализацияТоваровУслуг.Ссылка КАК Ссылка,

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

ИЗ

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

ГДЕ

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

Ключевым моментом здесь является конструкция ЗНАЧЕНИЕ(..). Без неё интерпретатор попытается найти поле или таблицу с таким именем и выдаст ошибку синтаксиса.

Использование такого подхода оправдано в хранимых процедурах или в запросах, где условия фильтрации жестко заданы логикой приложения и не зависят от ввода пользователя. Однако для динамических выборок этот метод менее гибок.

💡

Использование конструкции ЗНАЧЕНИЕ(Перечисление.Имя.Элемент) гарантирует, что запрос будет выполнен корректно даже если внутреннее представление данных в базе изменится.

Параметризация запросов для работы с перечислениями

Более гибким и рекомендуемым подходом является использование параметров запроса. Это позволяет передавать значения перечислений из внешнего кода (например, из формы или программного модуля) внутрь текста запроса. Такой метод повышает безопасность и переиспользуемость кода.

В тексте запроса параметр обозначается знаком &. Значение этому параметру присваивается в объекте запроса перед его выполнением. Платформа автоматически преобразует переданное значение перечисления в формат, понятный СУБД.

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

ТекстЗапроса ="ВЫБРАТЬ

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

ИЗ

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

ГДЕ

Справочник.Контрагенты.Вид = &ВидКонтрагента";

Запрос = Новый Запрос(ТекстЗапроса);

Запрос.УстановитьПараметр("ВидКонтрагента", Перечисления.ВидыКонтрагентов.ЮридическоеЛицо);

Результат = Запрос.Выполнить;

Обратите внимание, что в методе УстановитьПараметр мы передаем непосредственно значение из глобального контекста Перечисления. Не нужно оборачивать его в строку или делать лишние преобразования. Тип данных сохраняется.

Если необходимо передать список значений (например, выбрать документы с несколькими статусами), используется временная таблица значений. Это стандартный паттерн для работы с множественными условиями IN в 1С.

📊 Какой способ передачи перечисления вы используете чаще?
Прямое значение в запросе
Параметры запроса
Временные таблицы
Через таблицу значений

Использование таблицы значений для множественного выбора

Часто возникает задача отфильтровать данные по нескольким значениям перечисления одновременно. Например, нужно найти все заказы, которые находятся в статусах"В работе","На согласовании" или"Оплачен". Простое перечисление через ИЛИ в условии ГДЕ делает запрос громоздким и трудночитаемым.

Оптимальным решением является создание таблицы значений, заполнение её необходимыми элементами перечисления и соединение этой таблицы с основной выборкой. Это позволяет использовать конструкцию ВНУТРЕННЕЕ СОЕДИНЕНИЕ или условие вхождения.

Процесс выглядит следующим образом: создается объект ТаблицаЗначений, в него добавляются колонки с типом ПеречислениеСсылка. Затем в цикле или списком добавляются нужные элементы. Эта таблица передается в запрос как параметр.

Этап Действие Результат
1 Создание ТЗ Пустая таблица с колонкой"Статус"
2 Заполнение Добавлены строки: Черновик, Проведен
3 Передача в запрос Параметр &ТаблицаСтатусов
4 Выполнение Выборка только нужных записей

В тексте запроса это реализуется через временную таблицу. Вы загружаете параметр-таблицу во временное хранилище запроса (конструкция КАК &Имя) и соединяете её с основным набором данных.

ТЗ = Новый ТаблицаЗначений;

ТЗ.Колонки.Добавить("Статус", ОписаниеТипов("ПеречислениеСсылка.СтатусыЗаказа"));

ТЗ.Добавить.Статус = Перечисления.СтатусыЗаказа.Новый;

ТЗ.Добавить.Статус = Перечисления.СтатусыЗаказа.ВРаботе;

Запрос.Текст ="ВЫБРАТЬ.. ИЗ.. ВНУТРЕННЕЕ СОЕДИНЕНИЕ &ТаблицаСтатусов КАК ТСтатусы ПО..";

Запрос.УстановитьПараметр("ТаблицаСтатусов", ТЗ);

Такой подход масштабируем. Вы можете передавать хоть 10, хоть 100 значений перечисления, и структура запроса останется неизменной. Это также упрощает отладку, так как содержимое таблицы значений можно легко посмотреть в отладчике.

⚠️ Внимание: Убедитесь, что тип колонки в Таблице Значений точно совпадает с типом поля в основной таблице базы данных. Несовпадение типов (например, ПеречислениеСсылка vs Строка) приведет к ошибке выполнения или пустому результату.

Получение перечисления по строковому имени

В некоторых сценариях, например при обработке данных из внешних источников (XML, JSON, HTTP-сервисы), значение перечисления приходит в виде строки. Нам необходимо преобразовать эту строку в объект перечисления, чтобы использовать его в запросе.

Для этого в встроенном языке существует метод Перечисления.Получить или прямой доступ через индексацию. Однако наиболее надежным способом является использование функции ЗначениеИзСтрокиВнутр или явное приведение типов, если имя элемента известно.

Если имя элемента динамическое, можно воспользоваться конструкцией обращения к коллекции перечислений по имени. Это позволяет избежать жесткой привязки кода к конкретным элементам на этапе компиляции.

  • 🔍 Используйте метод Метаданные.Перечисления.Найти для поиска описания перечисления по имени.
  • ⚙️ Применяйте ПолучитьПеречисление(Имя) для получения конкретного элемента из коллекции.
  • 🛡️ Всегда оборачивайте получение по строке в блок Попытка..Исключение, так как строка может не соответствовать ни одному элементу.

Пример безопасного получения значения:

ИмяЭлемента ="Черновик"; // Пришло из внешнего файла

Попытка

ЗначениеПеречисления = Перечисления.СтатусыДокумента[ИмяЭлемента];

// Далее используем ЗначениеПеречисления в запросе

Исключение

Сообщить("Неверное значение статуса:" + ИмяЭлемента);

КонецПопытки;

Важно отметить, что обращение по индексу (строковому имени) работает только если имя элемента точно совпадает с идентификатором в метаданных. Синонимы или представления здесь не подойдут.

Почему не стоит хранить имена перечислений в строках?

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

Типичные ошибки и способы их устранения

При работе с перечислениями в запросах разработчики часто сталкиваются с рядом типовых проблем. Понимание природы этих ошибок позволяет сократить время отладки.

Одной из самых частых ошибок является попытка сравнить поле типа ПеречислениеСсылка со строковой константой без явного преобразования. Система 1С строго следит за типами данных и не выполняет неявное приведение в условиях запроса.

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

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

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

⚠️ Внимание: Интерфейсы и возможности платформы 1С могут обновляться. Всегда проверяйте документацию к вашей конкретной версии платформы (8.3.20, 8.3.25 и т.д.), так как синтаксис некоторых функций может эволюционировать.

☑️ Проверка корректности работы с перечислением

Выполнено: 0 / 1

Часто задаваемые вопросы (FAQ)

Можно ли использовать синоним элемента перечисления в запросе?

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

Что делать, если элемент перечисления был удален из конфигурации?

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

Как передать значение перечисления из внешней обработки в основной запрос?

Самый надежный способ — создать параметр в запросе основной обработки и передать в него значение, полученное во внешней обработке, используя механизм внешних обработок или COM-соединение, приведя значение к типу ПеречислениеСсылка.

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

Нет, использование перечислений в условиях ГДЕ не снижает производительность. На уровне СУБД они хранятся как уникальные идентификаторы (GUID), и сравнение происходит так же быстро, как и для любых других ссылок.

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

В самом тексте запроса динамическая подстановка имен невозможна. Однако вы можете сформировать текст запроса программно во встроенном языке, подставив нужное имя элемента в строку запроса перед его компиляцией.