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

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

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

Причина проблемы: Агрессивная оптимизация компоновщика

Основная причина кроется в механизме работы СКД. В отличие от консоли запросов, которая выполняет текст «как есть», СКД выступает в роли интеллектуального построителя. Она анализирует текущие настройки отчета (выбранные поля, группировки, отборы) и динамически перестраивает исходный запрос, чтобы исключить из него «лишние» данные. Если компоновщик «считает», что данные из конкретной временной таблицы не используются в итоговом результате или не влияют на него, он просто вырезает создание этой таблицы из финального запроса. Однако, если на эту таблицу остаются ссылки в последующих соединениях (особенно при использовании ВНУТРЕННЕЕ СОЕДИНЕНИЕ), выполнение прерывается с ошибкой.

Метод 1: Использование роли поля «Обязательное»

Рассмотрим самый надежный программный способ заставить СКД «видеть» таблицу. В настройках набора данных есть колонка «Роли». Для полей, которые выбираются из проблемной временной таблицы, необходимо установить флаг «Обязательное».

Разберем, почему это помогает: когда мы помечаем поле как обязательное, мы даем компоновщику жесткое указание — это поле (и таблица-источник) должно присутствовать в конечном запросе вне зависимости от того, выбрал его пользователь в настройках отчета или нет. Проанализируем порядок действий:

  1. Переходим на вкладку «Набор данных».
  2. Находим поля, которые извлекаются из «исчезающей» временной таблицы.
  3. Нажимаем на кнопку в колонке «Роли».
  4. В открывшемся окне устанавливаем галочку «Обязательное».
  5. Сохраняем и проверяем работу отчета.

Метод 2: Настройка актуальности данных при использовании копий БД

Если ваша база данных использует механизм Дата-акселератора (копии базы данных), СКД может пытаться оптимизировать запрос для работы с копией, что иногда приводит к конфликтам с временными таблицами. Выясним причину: при определенных настройках система может решить, что данные в копии не требуют построения всех промежуточных звеньев.

В этом случае помогает установка параметра «Требуемая актуальность данных». Выполним следующие действия:

  1. Откроем схему компоновки данных.
  2. Перейдем на вкладку «Параметры» (или проверим свойства самого отчета в коде вызова).
  3. Установим значение «Актуальные». Это заставит систему обращаться к основной базе и выполнять запрос полностью без упрощений, характерных для акселератора.

Метод 3: Использование фиктивных условий в секции «ГДЕ»

Иногда СКД игнорирует таблицу, если считает ее содержимое константным или не влияющим на фильтрацию. Посмотрим на «хитрость», которую применяют опытные разработчики: добавление условия, которое всегда истинно, но задействует поля таблицы.

Например, если у нас есть временная таблица ВремяЗаявки, которая «теряется», мы можем добавить в итоговом запросе условие:


ГДЕ
    ВремяЗаявки.ЗаказС10До11 = ВремяЗаявки.ЗаказС10До11

Или, если мы работаем с количественными показателями:


ГДЕ
    ВремяЗаявки.ЗаказС10До11 >= 0

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

Метод 4: Отказ от соединений по «ИСТИНА»

В запросе автора часто встречается конструкция ВНУТРЕННЕЕ СОЕДИНЕНИЕ ... ПО ИСТИНА. С точки зрения классического SQL — это CROSS JOIN. Однако СКД крайне плохо относится к таким соединениям, если из одной из таблиц не выбираются поля для вывода. Система считает такое соединение бессмысленным и выбрасывает таблицу.

Рассмотрим, как сделать связь более «явной» для системы. Мы можем добавить во все временные таблицы искусственный ключ связи:


// В каждой временной таблице добавляем поле:
ВЫБРАТЬ
    1 КАК КлючСвязи,
    ...
ПОМЕСТИТЬ ВТ_Данные

Затем в финальном запросе заменим ПО ИСТИНА на логическую связь:


ИЗ
    ВТ_1 КАК Таблица1
    ВНУТРЕННЕЕ СОЕДИНЕНИЕ ВТ_2 КАК Таблица2
    ПО Таблица1.КлючСвязи = Таблица2.КлючСвязи

Это создает прозрачную структуру зависимостей, которую компоновщик обрабатывает гораздо стабильнее.

Метод 5: Анализ скомпонованного макета

Если ни один из методов не помогает, нам нужно проанализировать, какой именно текст запроса генерирует СКД в момент ошибки. Это можно сделать через отладку в коде вызова отчета. Посмотрим на пример кода для извлечения реального запроса:


КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
МакетКомпоновки = КомпоновщикМакета.Выполнить(СхемаКомпоновкиДанных, Настройки);
// В МакетКомпоновки.НаборыДанных.НаборДанных1.Запрос будет текст
// который реально уходит на сервер СУБД.

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

Дополнительные рекомендации

Не забывайте проверять Функциональные опции. Если объекты метаданных (документы или регистры), используемые в запросе, входят в состав функциональной опции, которая отключена в текущем сеансе, СКД молча вырежет обращение к ним. В консоли запросов функциональные опции обычно игнорируются, что и создает иллюзию «рабочего» запроса, который «ломается» в отчете.

Также обратите внимание на агрегатные функции. Если вы используете КОЛИЧЕСТВО(РАЗЛИЧНЫЕ ...) внутри временной таблицы без группировки (как в примере автора), попробуйте добавить фиктивную группировку по какому-либо полю, которое гарантированно есть в системе, чтобы структура таблицы выглядела для СКД более стандартно.

← На главную