При разработке на платформе 1С:Предприятие программисты часто сталкиваются с ситуацией, когда необходимо обработать данные, уже находящиеся в памяти (например, в Таблице Значений), с помощью механизма запросов. Ошибка Таблица не найдена является самой распространенной в этом сценарии. Разберем детально, почему она возникает и как правильно выстроить работу с временными таблицами.
Проанализируем исходную ситуацию. В коде автора таблица ТаблицаНаценок получена методом выгрузки из номенклатуры. Однако в тексте запроса к ней обращаются так, будто это постоянная таблица базы данных (например, справочник или регистр). Система не видит переменную ТаблицаНаценок внутри SQL-контекста, пока мы явно её туда не передадим.
Для исправления ситуации выполним два обязательных действия:
&, указывая, что это параметр.Запрос.УстановитьПараметр("ИмяПараметра", ТаблицаОбъект).Посмотрим на исправленный фрагмент кода:
// Подготовка данных
ТаблицаНаценок = Номенклатура.Выгрузить();
Запрос = Новый Запрос;
// В тексте обязательно используем &ТаблицаНаценок
Запрос.Текст =
"ВЫБРАТЬ
| ТаблицаНаценок.ТМЦ КАК ТМЦ,
| ТаблицаНаценок.Партия КАК ПАРТИЯ
|ПОМЕСТИТЬ ДанныеДокумента
|ИЗ
| &ТаблицаНаценок КАК ТаблицаНаценок
|;
|...дальнейший текст запроса...";
// Передаем таблицу в запрос
Запрос.УстановитьПараметр("ТаблицаНаценок", ТаблицаНаценок);
Даже если мы правильно передали параметр, 1С может выдать ошибку «Неверные параметры», если колонки таблицы не имеют строго определенных типов. Если ТаблицаНаценок создается программно, крайне важно инициализировать её с использованием ОписаниеТипов. Если типы не определены (содержат Произвольный тип), запрос не сможет сопоставить эти данные с полями регистров.
Рассмотрим пример правильного создания таблицы перед передачей в запрос:
МассивТМЦ = Новый Массив;
МассивТМЦ.Добавить(Тип("СправочникСсылка.Номенклатура"));
ОписаниеТМЦ = Новый ОписаниеТипов(МассивТМЦ);
ТаблицаДляЗапроса = Новый ТаблицаЗначений;
ТаблицаДляЗапроса.Колонки.Добавить("ТМЦ", ОписаниеТМЦ);
ТаблицаДляЗапроса.Колонки.Добавить("Партия", Новый ОписаниеТипов("СправочникСсылка.ПартииНоменклатуры"));
Без жесткой типизации соединение с виртуальными таблицами (например, СрезПоследних) может работать некорректно или вызывать критические ошибки выполнения.
В исходном сообщении автор использует конструкцию ПОМЕСТИТЬ тДокумента в конце запроса. Выясним причину, по которой РезультатЗапроса.Выгрузить() в этом случае вернет пустую таблицу. Когда последним словом в пакете запроса стоит ПОМЕСТИТЬ, данные записываются во временную таблицу в оперативной памяти (или в tempdb на сервере SQL), но не возвращаются в основной поток выполнения программы.
Чтобы получить результат, мы должны завершить пакет финальным выбором из этой временной таблицы:
// ... (предыдущие части запроса с ПОМЕСТИТЬ)
|;
|ВЫБРАТЬ
| Т.ТМЦ,
| Т.Партия,
| Т.НаценкаИмпорт
|ИЗ
| тДокумента КАК Т"; // Финальная выборка вернет данные в РезультатЗапроса
При соединении временной таблицы с большими регистрами (как в случае с РегистрСведений.ЦеныТМЦ), производительность системы может значительно упасть. Проанализируем, как ускорить выполнение:
ИНДЕКСИРОВАТЬ ПО для полей, по которым происходит связь (ТМЦ, Партия).Посмотрим на оптимизированный вариант структуры запроса:
Запрос.Текст =
"ВЫБРАТЬ
| Таблица.ТМЦ КАК ТМЦ,
| Таблица.Партия КАК Партия
|ПОМЕСТИТЬ ВтДанныеДокумента
|ИЗ
| &ТаблицаНаценок КАК Таблица
|ИНДЕКСИРОВАТЬ ПО
| ТМЦ,
| Партия
|;
|ВЫБРАТЬ
| ВтДанные.ТМЦ КАК ТМЦ,
| Цены.НаценкаИмпорт КАК НаценкаИмпорт
|ИЗ
| ВтДанныеДокумента КАК ВтДанные
| ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ЦеныТМЦ.СрезПоследних(&Период,
| ТМЦ В (ВЫБРАТЬ ТМЦ ИЗ ВтДанныеДокумента)) КАК Цены
| ПО ВтДанные.ТМЦ = Цены.ТМЦ И ВтДанные.Партия = Цены.Партия";
Важно: Использование ЛЕВОЕ СОЕДИНЕНИЕ гарантирует, что мы не потеряем строки из документа, для которых еще не установлена наценка в регистре. В этом случае в поле НаценкаИмпорт просто придет значение NULL, которое можно обработать функцией ЕСТЬNULL(Цены.НаценкаИмпорт, 0).
При написании запросов вручную легко допустить опечатку, которую трудно заметить. В исходном сообщении была ошибка: ПО Регист.ТМЦ = ДанныеДокумента.ТМЦ. Пропущена буква «р» в псевдониме таблицы Регистр. Рекомендуем всегда использовать Конструктор запроса — это исключает подобные ошибки, так как псевдонимы и поля выбираются из списка.
Для успешной работы с Таблицей Значений в запросе необходимо:
УстановитьПараметр с префиксом & в тексте.ВЫБРАТЬ, если требуется получить результат в коде.