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

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При работе с языком запросов «1С:Предприятие 8» разработчики часто сталкиваются с необходимостью использования значений констант. На первый взгляд кажется логичным использовать оператор ЗНАЧЕНИЕ(), по аналогии с перечислениями или предопределенными элементами. Однако при попытке написать ЗНАЧЕНИЕ(Константа.ВалютаУчета) система выдаст ошибку. В этой статье мы подробно разберем, почему так происходит, и рассмотрим все существующие способы получения констант в запросе.

Почему оператор ЗНАЧЕНИЕ() не работает для констант

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

  1. Перечисления (Enums): их значения создаются в конфигураторе и не меняются в процессе работы пользователя.
  2. Предопределенные элементы: справочники, планы видов характеристик, планы счетов, имеющие имя предопределенного элемента.
  3. Пустые ссылки: например, ЗНАЧЕНИЕ(Справочник.Контрагенты.ПустаяСсылка).
  4. Системные перечисления: значения типа Булево (ИСТИНА, ЛОЖЬ), типы цен и т.д.

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

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

Способ №1: Использование таблицы Константы (Левое соединение)

Это классический метод, который часто встречается в типовых конфигурациях (например, в ERP или УТ 11). Мы можем обратиться к виртуальной таблице Константы, которая содержит все константы базы в виде полей одной (виртуальной) строки. Рассмотрим, как это реализовано на практике.

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


ВЫБРАТЬ
    Продажи.Номенклатура КАК Номенклатура,
    Продажи.Количество КАК Количество,
    Константы.ВалютаРегламентированногоУчета КАК Валюта
ИЗ
    РегистрНакопления.Продажи КАК Продажи
        ЛЕВОЕ СОЕДИНЕНИЕ Константы КАК Константы
        ПО (ИСТИНА)

Важный нюанс: в современных версиях платформы (начиная с 8.2.14) физически каждая константа хранится в своей отдельной таблице (например, _Const1, _Const2). Это было сделано для оптимизации блокировок. Однако для удобства разработчиков 1С сохранила виртуальную таблицу Константы, обращение к которой платформа автоматически преобразует в нужные соединения на уровне SQL. При использовании этого метода стоит помнить, что если константа имеет составной тип, лучше использовать функцию ВЫРАЗИТЬ(), чтобы оптимизировать план выполнения запроса:


ВЫБРАТЬ
    ВЫРАЗИТЬ(Константы.ОсновнойСклад КАК Справочник.Склады) КАК Склад
ИЗ
    Константы КАК Константы

Способ №2: Передача значения через параметры (Рекомендуемый)

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

Рассмотрим более элегантный и производительный способ: получение значения в коде 1С и передача его в запрос как параметра. Это исключает лишние соединения таблиц внутри SQL-запроса.


// Получаем значение константы программно
ВалютаУчета = Константы.ВалютаРегламентированногоУчета.Получить();

Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |   Остатки.СуммаОстаток КАК Сумма
    |ИЗ
    |   РегистрНакопления.Взаиморасчеты.Остатки( , Валюта = &ПарамВалюта) КАК Остатки";

Запрос.УстановитьПараметр("ПарамВалюта", ВалютаУчета);
Результат = Запрос.Выполнить();

Преимущества этого метода:

  1. Читаемость: запрос становится проще и понятнее.
  2. Производительность: СУБД не нужно выполнять JOIN с таблицами констант.
  3. Гибкость: если значение константы не заполнено, вы можете обработать эту ситуацию в коде до выполнения запроса.

Способ №3: Вложенный запрос в списке выбора

Существует еще один способ, который позволяет получить значение константы без явного прописывания соединений в секции СВЯЗИ. Это использование подзапроса прямо в полях выбора. Рассмотрим этот вариант:


ВЫБРАТЬ
    Документ.Номер КАК Номер,
    Документ.Дата КАК Дата,
    (ВЫБРАТЬ ВалютаРегламентированногоУчета ИЗ Константы) КАК Валюта
ИЗ
    Документ.РеализацияТоваровУслуг КАК Документ
ГДЕ
    Документ.Ссылка = &Ссылка

Такой подход удобен, когда значение константы нужно получить «точечно» и вы не хотите загромождать структуру связей основного запроса. Однако помните, что на уровне СУБД это все равно приведет к обращению к таблице констант. Для быстрой отладки и проверки подобных конструкций запросов можно использовать консоль запросов для управляемых форм.

Историческая справка и особенности блокировок

Разберем, почему в старых темах на форумах часто обсуждают «удобство» или «неудобство» работы с константами. В версии 8.0 и 8.1 все константы хранились в одной строке одной таблицы. Это означало, что любое изменение любой константы блокировало всю таблицу целиком. Если один бухгалтер менял префикс организации, другой не мог в это время провести документ, требующий чтения константы «Способ оценки МПЗ».

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

Итоги: что выбрать?

Проанализировав все варианты, мы можем дать следующие рекомендации:

Таким образом, хотя оператор ЗНАЧЕНИЕ() не поддерживает константы, платформа предоставляет гибкие альтернативы для эффективной работы с этими данными.

← На главную