Как исправить ошибку «Содержимое объекта данных может быть выбрано только во временную таблицу» в запросе 1С?

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

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

Анализ исходного запроса и выяснение причины ошибки

Посмотрим на исходный пакет запросов, вызвавший исключение платформы:


ВЫБРАТЬ
    Номенклатура.Ссылка КАК Номенклатура
ПОМЕСТИТЬ ТАБНК
ИЗ
    Справочник.Номенклатура КАК Номенклатура
ГДЕ
    Номенклатура.Артикул = &Артикул
;
ВЫБРАТЬ
    ТоварыОрганизацийОстатки.НомерГТД КАК ГТД,
    ТоварыОрганизацийОстатки.АналитикаУчетаНоменклатуры.Номенклатура КАК Номенклатура,
    ТоварыОрганизацийОстатки.КоличествоОстаток КАК КоличествоОстаток
ИЗ
    РегистрНакопления.ТоварыОрганизаций.Остатки(
            ,
            АналитикаУчетаНоменклатуры.Номенклатура В (ВЫБРАТЬ ТАБНК.Номенклатура ИЗ &ТАБНК КАК ТАБНК) И Организация = &Орг
    ) КАК ТоварыОрганизацийОстатки

Платформа выдает ошибку: «содержимое объекта данных может быть выбрано только во временную таблицу». Выясним причину такого поведения.

Символ амперсанда & в языке запросов 1С указывает на использование внешнего параметра, переданного в запрос через метод УстановитьПараметр(). Если после ключевого слова ИЗ указывается конструкция с амперсандом (например, ИЗ &ТАБНК), движок платформы ожидает внешний объект данных встроенного языка (например, ТаблицаЗначений или ТабличнаяЧасть).

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

Решение проблемы: правильное обращение к созданной временной таблице

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


ВЫБРАТЬ
    ТоварыОрганизацийОстатки.НомерГТД КАК ГТД,
    ТоварыОрганизацийОстатки.АналитикаУчетаНоменклатуры.Номенклатура КАК Номенклатура,
    ТоварыОрганизацийОстатки.КоличествоОстаток КАК КоличествоОстаток
ИЗ
    РегистрНакопления.ТоварыОрганизаций.Остатки(
            ,
            АналитикаУчетаНоменклатуры.Номенклатура В (ВЫБРАТЬ ТАБНК.Номенклатура ИЗ ТАБНК КАК ТАБНК) И Организация = &Орг
    ) КАК ТоварыОрганизацийОстатки

После удаления лишнего амперсанда синтаксическая ошибка исчезает, и запрос успешно выполняется.

Анализ альтернативного варианта: обращение через точку в параметрах виртуальной таблицы

В обсуждении предложен альтернативный вариант без использования первой временной таблицы:


ВЫБРАТЬ
    ТоварыОрганизацийОстатки.НомерГТД КАК ГТД,
    ТоварыОрганизацийОстатки.АналитикаУчетаНоменклатуры.Номенклатура КАК Номенклатура,
    ТоварыОрганизацийОстатки.КоличествоОстаток КАК КоличествоОстаток
ИЗ
    РегистрНакопления.ТоварыОрганизаций.Остатки(
            ,
            АналитикаУчетаНоменклатуры.Номенклатура.Артикул = &Артикул И Организация = &Орг
    ) КАК ТоварыОрганизацийОстатки

Проанализируем этот подход с точки зрения производительности и стандартов разработки 1С. Такая запись кажется компактной, но скрывает серьезные проблемы:

  1. Неявные соединения: Измерение АналитикаУчетаНоменклатуры ссылается на справочник КлючиАналитикиУчетаНоменклатуры. Конструкция АналитикаУчетаНоменклатуры.Номенклатура.Артикул приводит к двум последовательным операциям LEFT JOIN в формируемом SQL-запросе.
  2. Неоптимальный план выполнения СУБД: При разыменовании полей и использовании подзапросов внутри параметров виртуальной таблицы СУБД не может эффективно задействовать кластерные индексы итогов регистра. Это приводит к полному сканированию таблиц остатков вместо быстрого поиска по индексу, что критически замедляет работу системы на реальных базах.

Рекомендуемые способы оптимизации запроса

Рассмотрим, как правильно организовать получение остатков в соответствии со стандартами 1С:

  1. Подготовка списка аналитик во временной таблице с индексацией:

    Если требуется фильтровать остатки в запросе, правильная цепочка должна оперировать прямым измерением регистра:

    
    ВЫБРАТЬ
        Номенклатура.Ссылка КАК Ссылка
    ПОМЕСТИТЬ ВТ_Номенклатура
    ИЗ
        Справочник.Номенклатура КАК Номенклатура
    ГДЕ
        Номенклатура.Артикул = &Артикул
    ИНДЕКСИРОВАТЬ ПО
        Ссылка
    ;
    ВЫБРАТЬ
        Ключи.Ссылка КАК Ссылка
    ПОМЕСТИТЬ ВТ_КлючиАналитики
    ИЗ
        Справочник.КлючиАналитикиУчетаНоменклатуры КАК Ключи
    ГДЕ
        Ключи.Номенклатура В (ВЫБРАТЬ ВТ_Номенклатура.Ссылка ИЗ ВТ_Номенклатура КАК ВТ_Номенклатура)
    ИНДЕКСИРОВАТЬ ПО
        Ссылка
    ;
    ВЫБРАТЬ
        ТоварыОрганизацийОстатки.НомерГТД КАК ГТД,
        ТоварыОрганизацийОстатки.АналитикаУчетаНоменклатуры.Номенклатура КАК Номенклатура,
        ТоварыОрганизацийОстатки.КоличествоОстаток КАК КоличествоОстаток
    ИЗ
        РегистрНакопления.ТоварыОрганизаций.Остатки(
                ,
                АналитикаУчетаНоменклатуры В (ВЫБРАТЬ ВТ_КлючиАналитики.Ссылка ИЗ ВТ_КлючиАналитики КАК ВТ_КлючиАналитики) И Организация = &Орг
        ) КАК ТоварыОрганизацийОстатки
    ;
    УНИЧТОЖИТЬ ВТ_Номенклатура
    ;
    УНИЧТОЖИТЬ ВТ_КлючиАналитики
    

    Обратите внимание на использование конструкции ИНДЕКСИРОВАТЬ ПО — это позволяет оптимизатору СУБД мгновенно соединять данные. В конце пакета обязательно добавляем УНИЧТОЖИТЬ для освобождения ресурсов базы данных.

  2. Получение параметров на стороне встроенного языка:

    Если артикул уникален и по нему находится одна позиция номенклатуры, значительно эффективнее найти номенклатуру и связанные ключи аналитики предварительно в коде модуля 1С, а затем передать готовый массив ссылок в параметр &МассивАналитик. Тогда условие виртуальной таблицы сведется к прямому отбору АналитикаУчетаНоменклатуры В (&МассивАналитик) И Организация = &Орг, обеспечивающему максимальную скорость расчета остатков.

← На главную