Почему перестал работать запрос с обращением через точку после обновления на платформу 8.3.24 без режима совместимости?

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

При переходе на новые версии платформы 1С:Предприятие 8.3.24 (а также 8.3.21 и 8.3.22) с одновременным отключением или повышением режима совместимости разработчики часто сталкиваются с ошибкой «Поле не найдено». Ситуация выглядит парадоксально: код, который годами стабильно работал в ERP, УТ или КА, внезапно начинает выдавать исключение. Особенно это касается запросов, где в качестве источника данных выступает Таблица Значений (ТЗ), передаваемая через параметр.

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

Проанализируем исходную проблему

Рассмотрим типичный пример запроса, который вызывает ошибку на платформе 8.3.24. Проблема возникает в момент помещения данных из внешней таблицы во временную таблицу. В запросе присутствует обращение к реквизиту ссылки через точку:


ВЫБРАТЬ
    Товары.Номенклатура КАК Номенклатура,
    ВЫБОР
        КОГДА Товары.Серия = ЗНАЧЕНИЕ(Справочник.СерииНоменклатуры.ПустаяСсылка)
            ТОГДА 9999999999
        ИНАЧЕ ВЫРАЗИТЬ(РАЗНОСТЬДАТ(&ТекущаяДата, 
              ВЫРАЗИТЬ(Товары.Серия КАК Справочник.СерииНоменклатуры).ГоденДо, ДЕНЬ) КАК Число(10))
    КОНЕЦ КАК КоличествоДнейДоОкончанияСрокаГодности
ПОМЕСТИТЬ ВременнаяТаблицаТовары
ИЗ
    &Товары КАК Товары

Начиная с версии 8.3.24, система сообщает, что поле ГоденДо не найдено, хотя визуально в конструкции ВЫРАЗИТЬ указан верный тип справочника. Выясним причину такого поведения.

Выясним причину: почему платформа больше не «видит» поле?

Основная причина кроется в новом оптимизаторе запросов и ужесточении правил валидации метаданных при отключенном режиме совместимости. Разберем ситуацию по пунктам:

  1. Строгая проверка путей на этапе компиляции. Раньше платформа могла игнорировать проверку реквизитов внутри блока ВЫБОР КОГДА, если в данных попадалась пустая ссылка или условие не выполнялось. Теперь же при отсутствии режима совместимости выполняется полная проверка всех путей запроса еще до его фактического выполнения.
  2. Неявные соединения из параметров. Обращение Товары.Серия.ГоденДо — это типичное неявное соединение (LEFT JOIN). Когда источником данных является параметр &Товары, платформа не может на 100% гарантировать связь между колонкой этой «виртуальной» таблицы и физической таблицей в базе данных в момент создания временной таблицы.
  3. Запрет сложных преобразований при создании ВТ. В режиме совместимости 8.3.24 механизм помещения данных во временную таблицу требует максимальной простоты. Попытка «прыгнуть» через точку в другую таблицу метаданных (справочник СерииНоменклатуры) из внешнего источника данных (ТЗ) теперь считается некорректной операцией.

Важный нюанс: даже если вы используете ВЫРАЗИТЬ(Серия КАК Справочник...), анализатор запроса может «потерять» эту типизацию, так как сама ТЗ в оперативной памяти не является частью структуры БД.

Решение №1: Разделение запроса на этапы (Рекомендуемый способ)

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

Шаг 1: Помещаем ТЗ во временную таблицу «как есть». Мы просто копируем данные из параметра в базу, не пытаясь обращаться к реквизитам ссылок.


ВЫБРАТЬ
    Товары.КлючСвязи,
    Товары.Номенклатура,
    Товары.Серия
ПОМЕСТИТЬ ВТ_Товары_СырыеДанные
ИЗ
    &Товары КАК Товары;

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


ВЫБРАТЬ
    ВТ.КлючСвязи,
    ВТ.Номенклатура,
    ВЫБОР
        КОГДА ВТ.Серия = ЗНАЧЕНИЕ(Справочник.СерииНоменклатуры.ПустаяСсылка)
            ТОГДА 9999999999
        ИНАЧЕ РАЗНОСТЬДАТ(&ТекущаяДата, ТабСерии.ГоденДо, ДЕНЬ)
    КОНЕЦ КАК КоличествоДнейДоОкончанияСрокаГодности
ИЗ
    ВТ_Товары_СырыеДанные КАК ВТ
    ЛЕВОЕ СОЕДИНЕНИЕ Справочник.СерииНоменклатуры КАК ТабСерии
        ПО ВТ.Серия = ТабСерии.Ссылка

Решение №2: Проверка типизации таблицы значений в коде

Проанализируем ситуацию: иногда ошибка возникает из-за того, что колонка в ТЗ не имеет четкого описания типа. Если колонка Серия создана просто как «объект» или содержит разные типы, платформа 8.3.24 без режима совместимости не сможет построить план запроса.

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


МассивТипов = Новый Массив;
МассивТипов.Добавить(Тип("СправочникСсылка.СерииНоменклатуры"));
ОписаниеТипаСерии = Новый ОписаниеТипов(МассивТипов);

ТЗ_Товары = Новый ТаблицаЗначений;
ТЗ_Товары.Колонки.Добавить("Серия", ОписаниеТипаСерии);
// ... заполнение таблицы

Хотя этот метод помогает в ряде случаев, практика показывает, что на платформе 8.3.24 даже с типизированной ТЗ лучше использовать Решение №1 (явное соединение через временную таблицу), так как это более надежно с точки зрения работы оптимизатора.

Решение №3: Корректировка порядка операторов

Иногда в расширениях или старых запросах встречается ситуация, когда соединение таблиц происходит в блоке ГДЕ или после него некорректно. На платформе 8.3.24 важно соблюдать строгую последовательность. Рассмотрим пример исправления:

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

Новый стиль: сначала описываем все СОЕДИНЕНИЯ в секции ИЗ, а затем обращаемся к полям этих таблиц в секции ВЫБРАТЬ.

Проанализируем итог: если вы обновились до 8.3.24 и увидели ошибку «Поле не найдено» в запросе с ТЗ, не спешите возвращать режим совместимости. Это хороший повод оптимизировать код. Разделение запроса на «помещение данных» и «обработку данных с джоинами» не только решает проблему совместимости, но и зачастую ускоряет выполнение запроса на больших объемах данных, так как оптимизатору проще построить верный план выполнения.

← На главную