Почему в запросе 1С возникает ошибка «Таблица не найдена» при использовании временных таблиц?

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

При разработке механизмов проведения документов или создании сложных отчетов в 1С:Предприятие 8 программисты часто сталкиваются с ошибкой вида: {(26, 20)}: Таблица не найдена "ВТВремя". Эта проблема может поставить в тупик, особенно когда код кажется логически верным и написанным «по канонам». Давайте подробно разберем, почему система «теряет» таблицы, и как правильно организовать работу с временными данными в запросах.

Причина 1: Пересоздание объекта «Запрос»

Проанализируем типичную ситуацию, описанную в обсуждении. Разработчик создает временную таблицу в одном месте кода, а затем пытается обратиться к ней в другом. Главная ошибка здесь кроется в строке Запрос = Новый Запрос;. В 1С объект Запрос является изолированным контейнером. Как только вы инициализируете переменную Запрос заново, старый объект со всеми его временными таблицами уничтожается в памяти сервера, и новый объект о них ничего не знает.

Рассмотрим пример ошибочного кода:


// Первый запрос создает таблицу
Запрос1 = Новый Запрос("ВЫБРАТЬ Ссылка ПОМЕСТИТЬ ВТДанные ИЗ Справочник.Номенклатура");
Запрос1.Выполнить();

// Второй запрос пытается к ней обратиться - ТУТ БУДЕТ ОШИБКА
Запрос2 = Новый Запрос("ВЫБРАТЬ * ИЗ ВТДанные");
Результат = Запрос2.Выполнить(); 

В данном случае Запрос2 не имеет доступа к пространству имен Запрос1. Чтобы решить эту проблему, необходимо использовать Менеджер временных таблиц. Это специальный объект, который выступает «хранилищем» для временных таблиц и может передаваться между разными запросами.

Разберем правильный алгоритм работы с менеджером:

  1. Создаем объект МенеджерВременныхТаблиц.
  2. Назначаем этот менеджер свойству МенеджерВременныхТаблиц первого запроса.
  3. Выполняем запрос с инструкцией ПОМЕСТИТЬ.
  4. Назначаем тот же самый менеджер второму запросу.

Пример корректного кода:


МенеджерВТ = Новый МенеджерВременныхТаблиц;

Запрос1 = Новый Запрос;
Запрос1.МенеджерВременныхТаблиц = МенеджерВТ;
Запрос1.Текст = "ВЫБРАТЬ Ссылка ПОМЕСТИТЬ ВТ_Товары ИЗ Справочник.Номенклатура";
Запрос1.Выполнить();

Запрос2 = Новый Запрос;
Запрос2.МенеджерВременныхТаблиц = МенеджерВТ;
Запрос2.Текст = "ВЫБРАТЬ * ИЗ ВТ_Товары"; // Теперь таблица видна!
Результат = Запрос2.Выполнить();

Причина 2: Попытка соединения с параметром-таблицей

Выясним еще один важный нюанс. Часто в запрос передается внешняя таблица (например, ТаблицаЗначений) через параметр: Запрос.УстановитьПараметр("ВТВремя", ТЗ_Данные);. Ошибка возникает при попытке выполнить ЛЕВОЕ СОЕДИНЕНИЕ напрямую с этим параметром. В языке запросов 1С нельзя соединять физические таблицы или временные таблицы с параметрами напрямую.

Решение: Параметр-таблицу необходимо сначала превратить в настоящую временную таблицу (ВТ). Это делается с помощью конструкции ПОМЕСТИТЬ в первом пакете запроса.

Рассмотрим, как это выглядит в тексте запроса:


// Пакет №1: Создаем ВТ из параметра
ВЫБРАТЬ
    ТЗ.Поле1 КАК Поле1,
    ТЗ.Поле2 КАК Поле2
ПОМЕСТИТЬ ВТ_ИзПараметра
ИЗ
    &ПараметрТаблица КАК ТЗ;

////////////////////////////////////////////////////////////////////////////////
// Пакет №2: Используем созданную ВТ в соединении
ВЫБРАТЬ
    Спр.Ссылка,
    ВТ.Поле2
ИЗ
    Справочник.Номенклатура КАК Спр
    ЛЕВОЕ СОЕДИНЕНИЕ ВТ_ИзПараметра КАК ВТ
    ПО Спр.Наименование = ВТ.Поле1

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

Причина 3: Жизненный цикл и область видимости ВТ

Проанализируем ситуацию, когда разработчик использует консоль запросов. В консоли таблицы часто «подхватываются» автоматически, но в реальном коде модуля (например, в ОбработкаПроведения) нужно строго соблюдать последовательность. Если вы не использовали ПОМЕСТИТЬ, система будет искать таблицу ВТВремя в структуре метаданных (среди справочников, документов и регистров). Не найдя её там, она выдаст ошибку «Таблица не найдена».

Важные правила работы с пакетами:

Оптимизация: Индексация временных таблиц

Для того чтобы ЛЕВОЕ СОЕДИНЕНИЕ работало эффективно, особенно если во временной таблице содержатся тысячи строк, крайне рекомендуется индексировать поля связи. Это предотвратит замедление работы системы.

Посмотрим на пример с индексацией:


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

Завершение работы с временными таблицами

Временные таблицы занимают место в оперативной памяти или в базе данных tempdb на SQL-сервере. Хорошим тоном считается удаление таблиц после того, как они выполнили свою роль, особенно если используется МенеджерВременныхТаблиц, который живет долго.

Для удаления используется команда УНИЧТОЖИТЬ:

УНИЧТОЖИТЬ ВТ_Цены;

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

← На главную