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

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

В процессе разработки на платформе 1С:Предприятие часто возникает необходимость передать таблицу значений (ТЗ) в запрос, сохранить ее во временную таблицу и сразу же обратиться к реквизитам содержащихся в ней объектов. Разберем, почему попытки сделать это в одном пакете запроса приводят к ошибкам или некорректным результатам, и как правильно организовать такой код.

Анализ проблемы

Многие разработчики сталкиваются с ситуацией, когда запрос, использующий конструкцию ПОМЕСТИТЬ ВТ_Имя ИЗ &ПараметрТЗ, выдает «странный» результат или ошибку, если в том же пакете происходит попытка обращения к реквизитам через оператор ВЫРАЗИТЬ. Например:


ВЫБРАТЬ 
    ВЫРАЗИТЬ(&Контрагент КАК Справочник.Контрагенты).Наименование КАК Наименование
ПОМЕСТИТЬ ВТ_Товары 
ИЗ &Товары КАК Товары

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

Как решить эту задачу правильно?

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

  1. Этап 1: Чистое помещение данных. В первом пакете запроса мы только сохраняем содержимое ТаблицыЗначений во временную таблицу. Не пытайтесь здесь выполнять никакие вычисления или обращения к реквизитам.
  2. Этап 2: Выборка и соединение. Во втором пакете мы обращаемся к созданной временной таблице и уже соединяем её с нужными справочниками или документами базы данных, извлекая все необходимые поля.

Пример правильной реализации

Рассмотрим, как это выглядит в коде. Сначала мы подготавливаем ВТ_Товары без лишних обращений, а затем дополняем данные:


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

ВЫБРАТЬ 
    ВТ.НомерСтроки, 
    ВТ.Номенклатура, 
    ВТ.Контрагент, 
    ВТ.Контрагент.Наименование КАК Наименование, 
    ВТ.Контрагент.ИНН КАК ИНН
ИЗ ВТ_Товары КАК ВТ

Или, если вам нужно использовать ВЫРАЗИТЬ для приведения типа (например, если контрагент передается как УникальныйИдентификатор или ссылка общего типа), используйте такой подход:


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

ВЫБРАТЬ 
    ВТ.Номенклатура,
    ВЫРАЗИТЬ(&Контрагент КАК Справочник.Контрагенты).Наименование КАК Наименование
ИЗ ВТ_Товары КАК ВТ

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

Разберем ключевые моменты, которые помогут вам избежать проблем в будущем:

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

← На главную