Как исправить ошибку «Поле не найдено» в параметрах виртуальной таблицы при отключении режима совместимости в 1С?

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

Перевод конфигурации на новые версии платформы «1С:Предприятие» и отключение режима совместимости — это важный шаг для оптимизации системы и использования современных механизмов разработки. Однако этот процесс нередко преподносит сюрпризы в виде неожиданного изменения поведения старого, годами работавшего кода. С одной из таких проблем разработчики часто сталкиваются при обновлении до платформы 8.3.15 и отключении режима совместимости с версией 8.3.13 и ниже.

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

Симптомы проблемы и условия возникновения

Рассмотрим типичный сценарий. В конфигурации, где был отключен режим совместимости (или установлен в значение «Не использовать»), выполняется стандартный запрос к виртуальной таблице регистра накопления (например, РегистрНакопления.Продажи.Обороты). В параметрах этой таблицы (в секции отбора) используется измерение булева типа, которое напрямую сравнивается с логическим литералом ЛОЖЬ или ИСТИНА:


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

При выполнении этого запроса система неожиданно возвращает ошибку компиляции или выполнения следующего содержания:

Строка кода 5: {(5, 42)}: Поле не найдено "НеВключатьВСтатистику"
РегистрНакопления.Продажи.Обороты(, , , <<?>>НеВключатьВСтатистику = ЛОЖЬ) КАК ПродажиОбороты

При этом до отключения режима совместимости этот же запрос работал абсолютно корректно на протяжении многих лет. Более того, если добавить это поле в список выборки (секцию ВЫБРАТЬ) или убрать сравнение с литералом, ошибка пропадает. Выясним, почему так происходит.

Технические причины: зарегистрированная ошибка платформы

Описанное поведение является следствием официально признанного бага платформы «1С:Предприятие 8.3». В официальном баг-трекере фирмы «1С» эта ошибка зарегистрирована под номером 000062053 (также в базах данных партнеров она фигурирует под кодами 10214823 и 20050800).

Причина кроется в оптимизации механизмов трансляции запросов, которая была реализована в ветке платформы 8.3.15 при отключенном режиме совместимости. Изменения коснулись разбора логических выражений внутри параметров виртуальных таблиц (таких как .Остатки(), .Обороты(), .СрезПоследних() и др.) при взаимодействии с СУБД. При парсинге условий вида ИмяИзмерения = ЛОЖЬ или ИмяИзмерения = ИСТИНА внутренний транслятор запросов 1С теряет метаданные соответствующего булева поля, ошибочно полагая, что данное поле отсутствует в структуре виртуальной таблицы, и прерывает выполнение запроса.

Данная ошибка воспроизводится на большинстве релизов ветки 8.3.15 (например, 8.3.15.1489, 8.3.15.1830, 8.3.15.1869).

Способы решения проблемы

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

Решение 1: Использование оператора логического отрицания «НЕ» (Рекомендуемый быстрый способ)

Самый простой способ исправить код «здесь и сейчас» без изменения логики получения данных и без потери производительности — это отказаться от явного сравнения булева поля с литералами ЛОЖЬ и ИСТИНА. Платформа корректно транслирует логическое отрицание булевых переменных.

Давайте перепишем исходный запрос, применив оператор отрицания:


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

Если бы нам требовалось отобрать записи со значением ИСТИНА, мы бы просто указали имя поля без каких-либо дополнительных знаков равенства:


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

При таком написании транслятор запросов 1С не спотыкается на литералах, корректно сопоставляет поле с метаданными виртуальной таблицы и успешно выполняет запрос в СУБД.

Решение 2: Передача булева значения через параметр запроса

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

Рассмотрим пример реализации на языке 1С:


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

// Передаем значение Ложь через параметр
Запрос.УстановитьПараметр("ОтборПоСтатистике", Ложь);
РезультатЗапроса = Запрос.Выполнить();

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

Решение 3: Перенос условия в секцию ГДЕ (Не рекомендуется)

Иногда разработчики переносят отбор из параметров виртуальной таблицы в общую секцию ГДЕ. Выглядит это следующим образом:


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

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

Решение 4: Добавление поля в секцию ВЫБРАТЬ

Если добавить измерение НеВключатьВСтатистику в список выбираемых полей, ошибка действительно исчезнет, так как платформа будет вынуждена явно выгрузить метаданные этого поля в результирующий набор. Однако помните, что для виртуальных таблиц оборотов или остатков добавление нового измерения в секцию ВЫБРАТЬ приведет к изменению группировки результата запроса. Данные начнут разворачиваться и дублироваться в разрезе этого булева флага, что исказит итоговую выборку и сломает логику отчета.

Кардинальное решение: Обновление платформы

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

Проанализируем версии платформы, в которых была устранена ошибка 000062053:

Резюме

Мы проанализировали специфический сбой платформы 1С при работе с булевыми полями в параметрах виртуальных таблиц после отключения режима совместимости. Если ваша компания пока не готова к обновлению платформы на серверах, используйте безопасный обходной путь с заменой конструкции = ЛОЖЬ на оператор НЕ. Это позволит сохранить быстродействие системы и мгновенно возобновить работоспособность ваших алгоритмов.

← На главную