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

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

Стоит отметить, что неправильное использование типов данных в условиях отбора может значительно замедлить выполнение запроса, так как СУБД не сможет эффективно использовать индексы. Поэтому важно не просто знать синтаксис, но и понимать, как движок транслирует эти условия на язык базы данных. Мы рассмотрим как статические значения, так и динамические параметры, которые часто используются в СКД (Системе Компоновки Данных) и обычных запросах.

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

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

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

ВЫБРАТЬ

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

Документ.Статус

ИЗ

Документ.ЗаказКлиента КАК Документ

ГДЕ

Документ.Статус = &Статус.ВРаботе

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

  • 🔹 Использование оператора = для сравнения с одним значением перечисления.
  • 🔹 Применение оператора В для списка из нескольких констант.
  • 🔹 Автоматическая трансляция имен метаданных в значения СУБД при выполнении.
  • 🔹 Возможность комбинирования условий через логические операторы И и ИЛИ.

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

📊 Как вы чаще всего передаете значения перечислений в запрос?
Текстом прямо в запросе
Через параметры запроса
Через таблицу значений
Использую СКД

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

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

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

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

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

"ВЫБРАТЬ

| РегистрСведений.ЦеныНоменклатуры.Цена

|ИЗ

| РегистрСведений.ЦеныНоменклатуры КАК Цены

|ГДЕ

| Цены.ВидЦены = &ВидЦены";

Запрос.УстановитьПараметр("ВидЦены", Перечисления.ВидыЦен.Оптовая);

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

Важным нюансом является работа с неопределенными значениями. Если параметру присвоить значение Неопределено (Null), то условие сравнения вернет пустой набор записей, так как в SQL сравнение NULL = NULL или Field = NULL дает неизвестный результат (False). Для обработки таких ситуаций существуют специальные операторы, о которых пойдет речь ниже.

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

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

Операторы сравнения и работа с пустыми значениями

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

Для проверки на пустое значение следует использовать конструкцию ЕСТЬ NULL или сравнение с константой ЗНАЧЕНИЕ(Перечисление.Имя.ПустаяСсылка), хотя первый вариант более предпочтителен и читаем. Оператор ЕСТЬ NULL проверяет, является ли значение поля физически пустым в базе данных.

Оператор Описание Пример использования
= Равенство конкретному значению ГДЕ Статус = &Статус.Новый
В Вхождение в список значений ГДЕ Статус В (&СписокСтатусов)
ЕСТЬ NULL Проверка на пустую ссылку ГДЕ Статус ЕСТЬ NULL
НЕ Инверсия условия ГДЕ НЕ (Статус = &Статус.Завершен)

Частой ошибкой является попытка сравнить поле с пустой ссылкой через оператор равенства с параметром, имеющим значение Неопределено. Как упоминалось ранее, это не сработает ожидаемым образом. Если ваша логика требует обработки "отсутствия значения", используйте явную проверку на NULL.

💡

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

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

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

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

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

// Формирование таблицы значений в коде

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

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

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

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

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

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

"ВЫБРАТЬ

| Заказ.Ссылка

|ИЗ

| Документ.ЗаказКлиента КАК Заказ

| ВНУТРЕННЕЕ СОЕДИНЕНИЕ &ТЗСтатусов КАК ТЗ

| ПО Заказ.Статус = ТЗ.Статус";

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

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

⚠️ Внимание: Убедитесь, что имена колонок в таблице значений и типы данных точно соответствуют полям, с которыми производится соединение. Ошибка в типе колонки приведет к сбою выполнения запроса.

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

☑️ Проверка перед использованием таблицы значений

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

Особенности работы в Системе Компоновки Данных (СКД)

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

Пользователь может выбирать значения перечисления в окне настроек отчета. Важно правильно настроить список допустимых значений для параметра, чтобы пользователь не мог ввести некорректные данные. Это делается через свойство "Допустимые значения" в описании параметра схемы компоновки.

В тексте запроса внутри СКД синтаксис остается прежним: &Параметр. Однако система автоматически генерирует условия в зависимости от того, выбрано ли одно значение или несколько. Если в настройках отчета для параметра разрешен множественный выбор, СКД сама сформирует оператор В.

Как добавить все элементы перечисления в настройки СКД?

В схеме компоновки данных, в описании параметра, установите флаг "Использовать все значения перечисления по умолчанию". Это позволит отчету работать со всеми данными, если пользователь не выбрал конкретные фильтры.

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

Типичные ошибки и оптимизация производительности

Одной из самых распространенных ошибок является попытка сравнить поле перечисления со строковым представлением значения без использования специальных функций. Например, условие ГДЕ Статус = "ВРаботе" не сработает, так как типы несовместимы. Для сравнения со строкой нужно использовать функцию ЗНАЧЕНИЕ(), но это ухудшает читаемость и может повлиять на производительность.

Еще одна проблема — использование функций в условии отбора, например, ГДЕ Строка(Статус) = "ВРаботе". Такие условия делают запрос нефункционально зависимым от индексов, что заставляет СУБД выполнять полное сканирование таблицы. Всегда старайтесь сравнивать поля "как есть", используя типизированные значения.

  • ❌ Избегайте приведения типов в условии WHERE (например, Строка(Поле)).
  • ❌ Не используйте сравнение с строковыми литералами вместо констант метаданных.
  • ✅ Используйте параметры запроса для динамических значений.
  • ✅ Применяйте таблицу значений для больших списков отбора.

Оптимизация запросов с перечислениями также включает в себя анализ плана выполнения. Если вы видите, что запрос выполняется долго, проверьте, используется ли индекс по полю перечисления. В большинстве случаев стандартные индексы 1С по ссылкам и перечислениям работают корректно, если не нарушать правила типизации.

⚠️ Внимание: Интерфейс и возможности конструктора запросов могут меняться в разных версиях платформы 1С. Всегда проверяйте актуальность синтаксических конструкций в справочной системе вашей конкретной версии конфигуратора.

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

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

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

Что делать, если нужно отобрать записи по всем значениям перечисления, кроме одного?

Используйте оператор НЕ в сочетании с равенством или оператором В. Например: ГДЕ НЕ (Статус = &Статус.Удален) или ГДЕ Статус НЕ В (&СписокИсключений). Это позволит эффективно отфильтровать ненужные записи на уровне СУБД.

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

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

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

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

💡

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