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