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