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

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

В процессе разработки в системе 1С:Предприятие 8 программисты часто сталкиваются с ситуацией, когда запрос, который «вчера работал» или «подсмотрен в другой базе», внезапно выдает ошибку «Таблица не найдена». Особенно часто это происходит при попытке использовать временные таблицы для контроля остатков при проведении документов. Чтобы минимизировать подобные риски, полезно использовать статический анализатор кода проектов еще на этапе написания текста запроса. Давайте вместе разберем эту ситуацию на конкретном примере, выясним причины возникновения ошибки и найдем правильные способы её решения.

Проанализируем ситуацию

Рассмотрим код, который вызывает затруднения. В обработчике проведения документа создается объект МенеджерВременныхТаблиц, после чего выполняется запрос, который обращается к таблице с именем НоменклатураДокумента. Однако система возвращает ошибку, утверждая, что такой таблицы не существует. Посмотрим на фрагмент кода, который можно прогнать через помощник отладки для локализации проблемы:


МенеджерВТ = Новый МенеджерВременныхТаблиц;
Запрос3 = Новый Запрос;
Запрос3.МенеджерВременныхТаблиц = МенеджерВТ;
Запрос3.Текст = "ВЫБРАТЬ
                |   ОстаткиКомпьютеровОстатки.Деталь,
                |   ОстаткиКомпьютеровОстатки.КоличествоОстаток
                |ИЗ
                |   РегистрНакопления.ОстаткиКомпьютеров.Остатки(, 
                |       Деталь В (ВЫБРАТЬ НоменклатураДокумента.Деталь ИЗ НоменклатураДокумента)
                |   И Склад = &Склад) КАК ОстаткиКомпьютеровОстатки";

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

Выясним причину ошибки: Жизненный цикл временной таблицы

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

Чтобы таблица НоменклатураДокумента стала доступна для выбора (оператор ВЫБРАТЬ), она должна быть предварительно создана и наполнена данными с помощью оператора ПОМЕСТИТЬ. В коде автора этот этап полностью отсутствует. Система пытается найти в памяти таблицу, которую никто не создавал, и закономерно сообщает об ошибке.

Также важно обратить внимание на опечатки. В исходном сообщении фигурировало имя НомеклатураДокумента (пропущена буква «н»). 1С критична к именам объектов: даже если бы таблица была создана, ошибка «Таблица не найдена» всё равно возникла бы из-за несовпадения имен в коде создания и коде обращения.

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

Для того чтобы наш механизм контроля остатков заработал, нам необходимо выполнить три последовательных действия:

  1. Выгрузить данные из табличной части документа. Мы должны отобрать те товары или детали, которые указаны в текущем документе.
  2. Поместить эти данные во временную таблицу. На этом этапе мы даем таблице имя и сохраняем её в менеджере временных таблиц.
  3. Использовать временную таблицу в основном запросе. Теперь, когда таблица существует в памяти, мы можем накладывать на неё условия и соединять с другими таблицами (например, с остатками).

Решение №1: Использование пакетного запроса (рекомендуемый способ)

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

Рассмотрим правильный пример реализации:


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |   ПродажаСостав.Деталь КАК Деталь,
    |   СУММА(ПродажаСостав.Количество) КАК КоличествоВДокументе
    |ПОМЕСТИТЬ ВТ_НоменклатураДокумента
    |ИЗ
    |   Документ.Продажа.Состав КАК ПродажаСостав
    |ГДЕ
    |   ПродажаСостав.Ссылка = &Ссылка
    |СГРУППИРОВАТЬ ПО
    |   ПродажаСостав.Деталь
    |;
    |
    |////////////////////////////////////////////////////////////////////////////////
    |ВЫБРАТЬ
    |   Остатки.Деталь КАК Деталь,
    |   Остатки.КоличествоОстаток КАК КоличествоОстаток
    |ИЗ
    |   РегистрНакопления.ОстаткиКомпьютеров.Остатки(&Период, 
    |       Деталь В (ВЫБРАТЬ ВТ.Деталь ИЗ ВТ_НоменклатураДокумента КАК ВТ)
    |       И Склад = &Склад) КАК Остатки
    |ГДЕ
    |   Остатки.КоличествоОстаток < 0";

Запрос.УстановитьПараметр("Ссылка", Ссылка);
Запрос.УстановитьПараметр("Склад", Склад);
Запрос.УстановитьПараметр("Период", МоментВремени());

РезультатЗапроса = Запрос.Выполнить();

В этом примере первый запрос пакета выбирает данные из табличной части Состав документа Продажа и сохраняет их в память под именем ВТ_НоменклатураДокумента. Второй запрос уже видит эту таблицу и может с ней работать.

Решение №2: Использование Менеджера временных таблиц в разных запросах

Если по какой-то причине вам необходимо разделять запросы в коде (например, между разными функциями), нужно правильно передавать МенеджерВременныхТаблиц. Отладить такое взаимодействие и просмотреть содержимое таблиц поможет консоль запросов для управляемых форм. Проанализируем, как это сделать правильно:


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

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

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

Важный момент: если вы создадите Новый МенеджерВременныхТаблиц перед вторым запросом, он снова будет пустым, и вы получите ту же ошибку «Таблица не найдена».

Рассмотрим вопросы оптимизации

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

Мы рекомендуем добавлять инструкцию ИНДЕКСИРОВАТЬ ПО при создании временной таблицы. Это значительно ускорит работу фильтра в виртуальной таблице остатков:


ВЫБРАТЬ
    ПродажаСостав.Деталь КАК Деталь
ПОМЕСТИТЬ ВТ_НоменклатураДокумента
ИЗ
    Документ.Продажа.Состав КАК ПродажаСостав
ГДЕ
    ПродажаСостав.Ссылка = &Ссылка
ИНДЕКСИРОВАТЬ ПО
    Деталь

Подведем итоги

Чтобы избежать ошибки «Таблица не найдена» при работе с временными таблицами, придерживайтесь следующих правил:

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

← На главную