Почему в запросе возникает ошибка «Поле не найдено» при использовании ВЫРАЗИТЬ после обновления ERP?

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

Многие разработчики при переходе на новые релизы 1С:ERP Управление предприятием 2.5.12 (и аналогичные версии УТ 11.5 или КА 2.5) сталкиваются с неприятной ситуацией: код, который годами работал стабильно, внезапно начинает выдавать ошибку Поле не найдено. Особенно часто это проявляется в обработке Печать этикеток и ценников. Ситуация выглядит странно, так как синтаксис ВЫРАЗИТЬ(Поле КАК Справочник.Номенклатура).Реквизит кажется абсолютно корректным.

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

Проанализируем ситуацию: в чем суть ошибки?

Рассмотрим типичный фрагмент кода, который вызывает сбой. Проблема возникает в момент помещения данных из переданной таблицы значений (параметр &Таблица) во временную таблицу в запросе:


ВЫБРАТЬ
    ВЫРАЗИТЬ(ИсходныеДанные.Номенклатура КАК Справочник.Номенклатура) КАК Номенклатура,
    ВЫРАЗИТЬ(ИсходныеДанные.Номенклатура КАК Справочник.Номенклатура).НаборУпаковок КАК НаборУпаковок
ПОМЕСТИТЬ ВТ_Данные
ИЗ
    &Таблица КАК ИсходныеДанные

Система сообщает, что поле НаборУпаковок не найдено. Основная причина кроется в механизме работы платформы с временными таблицами, создаваемыми из внешних источников (Таблиц Значений). Когда мы обращаемся к реквизиту через точку (разыменование), платформа должна выполнить неявное соединение (Implicit Join) с таблицей справочника Номенклатура.

В последних версиях платформы (8.3.21 и выше), которые требуются для новых релизов ERP, контроль за выполнением запросов стал строже. Платформа больше не позволяет «пробрасывать» связи через точку для полей, которые еще не помещены в базу данных или не выбраны из физической таблицы. Так как &Таблица — это данные в памяти, находящиеся «вне» СУБД в момент разбора структуры, оптимизатор запроса блокирует попытку дотянуться до реквизитов справочника прямо в секции ПОМЕСТИТЬ.

Разберем по шагам правильное решение задачи

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

Шаг 1: Загрузка исходных данных во временную таблицу

На этом этапе мы выбираем из параметра &Таблица только сами ссылки и примитивные типы данных (количество, порядок и т.д.). Используем ВЫРАЗИТЬ только для типизации ссылочных полей, но не пытаемся получить их внутренние данные.


ВЫБРАТЬ
    ВЫРАЗИТЬ(ИсходныеДанные.Номенклатура КАК Справочник.Номенклатура) КАК Номенклатура,
    ВЫРАЗИТЬ(ИсходныеДанные.Характеристика КАК Справочник.ХарактеристикиНоменклатуры) КАК Характеристика,
    ИсходныеДанные.Количество КАК Количество
ПОМЕСТИТЬ ВТ_Исходник
ИЗ
    &Таблица КАК ИсходныеДанные
;

Шаг 2: Получение реквизитов через ЛЕВОЕ СОЕДИНЕНИЕ

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


ВЫБРАТЬ
    ВТ_Исходник.Номенклатура КАК Номенклатура,
    ВТ_Исходник.Характеристика КАК Характеристика,
    СпрНоменклатура.НаборУпаковок КАК НаборУпаковок,
    СпрНоменклатура.ЕдиницаИзмерения КАК ЕдиницаИзмерения,
    ВТ_Исходник.Количество КАК Количество
ИЗ
    ВТ_Исходник КАК ВТ_Исходник
    ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Номенклатура КАК СпрНоменклатура
        ПО ВТ_Исходник.Номенклатура = СпрНоменклатура.Ссылка

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

Рассмотрим альтернативный вариант («Быстрый фикс»)

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

Суть метода заключается в том, чтобы убрать обращение через точку из первого пакета запроса и перенести его во второй пакет, где данные уже выбраны из временной таблицы. Выясним причину эффективности этого метода: после того как данные помещены в ВТ_ИсходныеДанные, обращение ИсходныеДанные.Номенклатура.НаборУпаковок (через две точки) платформа уже может обработать, так как источник ИсходныеДанные уже является известной временной таблицей.

Посмотрим на пример кода, исправляющего текст запроса:


// Удаляем проблемные строки из секции ВЫБРАТЬ первого пакета
ТекстУдаления1 = "ВЫРАЗИТЬ(ИсходныеДанные.Номенклатура КАК Справочник.Номенклатура).НаборУпаковок КАК НаборУпаковок,";
Запрос.Текст = СтрЗаменить(Запрос.Текст, ТекстУдаления1, "");

ТекстУдаления2 = "ВЫРАЗИТЬ(ИсходныеДанные.Номенклатура КАК Справочник.Номенклатура).ЕдиницаИзмерения КАК ЕдиницаИзмерения,";
Запрос.Текст = СтрЗаменить(Запрос.Текст, ТекстУдаления2, "");

// В последующих пакетах заменяем обращение к полю ВТ на обращение через ссылку номенклатуры
Запрос.Текст = СтрЗаменить(Запрос.Текст, "ИсходныеДанные.НаборУпаковок", "ИсходныеДанные.Номенклатура.НаборУпаковок");
Запрос.Текст = СтрЗаменить(Запрос.Текст, "ИсходныеДанные.ЕдиницаИзмерения", "ИсходныеДанные.Номенклатура.ЕдиницаИзмерения");

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

Выводы и рекомендации

Подводя итоги нашего разбора, сформулируем основные правила работы с реквизитами из параметров-таблиц:

  1. Никогда не используйте разыменование (обращение через точку) к полям таблицы-параметра внутри команды ПОМЕСТИТЬ.
  2. Всегда типизируйте ссылочные поля в таблице значений перед передачей в запрос с помощью метода МассивТипов, но в самом запросе дополнительно используйте ВЫРАЗИТЬ для надежности.
  3. Если вам нужны дополнительные данные (например, Артикул, Вес или ЕдиницаИзмерения), получайте их во втором пакете запроса через ЛЕВОЕ СОЕДИНЕНИЕ с основной таблицей соответствующего справочника.
  4. Помните, что обновление конфигурации может изменить Версию совместимости платформы, что автоматически включает новые проверки синтаксиса запросов.

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

← На главную