Как правильно использовать временные таблицы и МенеджерВременныхТаблиц в 1С 8.3 Управляемые формы?

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

При работе с комплексными запросами в 1С часто возникает необходимость обработки больших объемов данных или выполнения многоступенчатых операций, когда результат одного запроса должен быть использован в последующем. Использование временных таблиц (ВТ) становится мощным инструментом для решения таких задач. Однако у многих разработчиков, особенно начинающих, возникают вопросы о том, как правильно объявлять, использовать и управлять жизненным циклом временных таблиц, особенно когда речь идет о передаче данных между различными пакетами запросов или даже между функциями.

В этой статье мы подробно рассмотрим, как эффективно работать с временными таблицами в 1С 8.3 на управляемых формах, выясним распространенные ошибки и изучим правильное применение объекта МенеджерВременныхТаблиц.

Понимание принципа работы временных таблиц в запросах 1С

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

Рассмотрим пример кода, где автор столкнулся с проблемой:


Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ
    |    Регистр1.Поле1 КАК Поле1,
    |    Регистр1.Поле2 КАК Поле2
    |ПОМЕСТИТЬ ВТ_Первая
    |ИЗ
    |    РегистрНакопления.Регистр1 КАК Регистр1
    |;
    |
    |ВЫБРАТЬ
    |    ВТ_Первая.Поле1 КАК ПолеА,
    |    Регистр2.Поле3 КАК ПолеБ
    |ИЗ
    |    ВТ_Первая КАК ВТ_Первая
    |        ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.Регистр2 КАК Регистр2
    |        ПО ВТ_Первая.Поле1 = Регистр2.Измерение1";
Результат = Запрос.Выполнить();

В этом коде временная таблица ВТ_Первая создается в первом пакете, и она корректно используется во втором пакете. Проблема, скорее всего, возникает не в этом сценарии, а когда пытаются использовать временную таблицу, созданную одним объектом Запрос, в другом, новом объекте Запрос. В таком случае, второй объект Запрос не будет "знать" о существовании временной таблицы, созданной предыдущим.

Решение: Объект МенеджерВременныхТаблиц

Для того чтобы временные таблицы стали доступны между разными объектами Запрос или даже между разными вызовами функций/процедур, нам необходимо использовать специальный объект 1С – МенеджерВременныхТаблиц. Этот объект выступает в роли контейнера, который управляет жизненным циклом и видимостью временных таблиц.

Шаг 1: Создание и привязка МенеджераВременныхТаблиц

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

  1. Создаем экземпляр МенеджерВременныхТаблиц:
  2. МенеджерВременныхТаблиц = Новый МенеджерВременныхТаблиц;
  3. Присваиваем его свойству МенеджерВременныхТаблиц каждого объекта Запрос:
  4. 
    Запрос = Новый Запрос;
    Запрос.МенеджерВременныхТаблиц = МенеджерВременныхТаблиц;
    // ... далее текст запроса
    

Таким образом, все запросы, которым мы присвоим один и тот же экземпляр МенеджерВременныхТаблиц, будут "видеть" временные таблицы, созданные в любом из этих запросов. Давайте посмотрим на исправленный пример автора:


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

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

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

Шаг 2: Передача МенеджераВременныхТаблиц между функциями

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


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

// Функция 2: ИспользоватьВТ
// Назначение: Использует ранее созданную временную таблицу "ВТ_Товары"
//             и объединяет ее с данными из регистра цен.
// Параметры: МенеджерВТ (МенеджерВременныхТаблиц) - объект, через который доступна ВТ.
// Возвращает: ТаблицуЗначений с товарами, их ссылками и ценами.
Функция ИспользоватьВТ(МенеджерВТ)
    // Создаем новый объект Запрос.
    Запрос = Новый Запрос;
    // Привязываем тот же менеджер временных таблиц,
    // чтобы текущий запрос мог "видеть" ВТ, созданную в другой функции.
    Запрос.МенеджерВременныхТаблиц = МенеджерВТ;
    Запрос.Текст = "ВЫБРАТЬ
        |    ВТ_Товары.Товар,   // Используем поле из временной таблицы
        |    ВТ_Товары.Ссылка, // Используем поле из временной таблицы
        |    Цены.Цена        // Объединяем с данными из регистра сведений
        |ИЗ
        |    ВТ_Товары КАК ВТ_Товары
        |        ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ЦеныНоменклатуры КАК Цены
        |        ПО ВТ_Товары.Ссылка = Цены.Номенклатура";
    // Выполняем запрос и выгружаем результат в ТаблицуЗначений.
    Возврат Запрос.Выполнить().Выгрузить();
КонецФункции

// Основной код, демонстрирующий использование функций
// Создаем общий менеджер временных таблиц.
МВТ = Новый МенеджерВременныхТаблиц;

// Вызываем первую функцию, которая создаст ВТ, используя наш МВТ.
СформироватьВТ(МВТ);

// Вызываем вторую функцию, которая использует ту же ВТ через тот же МВТ.
ТаблицаРезультат = ИспользоватьВТ(МВТ);

// Теперь в переменной ТаблицаРезультат находится ТаблицаЗначений
// с данными, сформированными на основе двух разных запросов,
// использующих общую временную таблицу.

Этот пример наглядно демонстрирует, как МенеджерВременныхТаблиц позволяет координировать работу с временными таблицами между различными частями кода, делая его более модульным и читаемым.

Жизненный цикл временных таблиц и МенеджераВременныхТаблиц

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

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

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

Очистка временных таблиц вручную

Хотя система 1С автоматически управляет удалением временных таблиц при уничтожении МенеджераВременныхТаблиц, в некоторых продвинутых сценариях может потребоваться явное удаление одной или нескольких временных таблиц до завершения работы менеджера. Для этого мы можем использовать оператор УНИЧТОЖИТЬ в тексте запроса. Этот оператор позволяет удалить конкретную временную таблицу по имени:


Запрос = Новый Запрос;
Запрос.МенеджерВременныхТаблиц = МенеджерВременныхТаблиц;
Запрос.Текст = "УНИЧТОЖИТЬ ВТ_Товары"; // Удаляем временную таблицу "ВТ_Товары"
Запрос.Выполнить();

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

Дополнительные возможности и сценарии использования

Помимо базового использования, МенеджерВременныхТаблиц предоставляет и другие возможности:

  1. Получение схемы временной таблицы: Свойство МенеджерВременныхТаблиц.ПолучитьОписаниеВременнойТаблицы(ИмяВременнойТаблицы) позволяет получить объект ОписаниеТаблицыЗапроса. Он содержит информацию о колонках, их типах и других свойствах временной таблицы. Это может быть полезно для динамического построения запросов или проверки структуры ВТ.
  2. Использование временных таблиц в процедурах общего модуля с параметрами: Как мы уже видели в примере, передача МенеджераВременныхТаблиц параметром в функции и процедуры общих модулей является стандартной практикой. Это позволяет централизовать логику формирования и обработки данных, делая ее более переиспользуемой.
  3. Оптимизация производительности: Временные таблицы могут значительно улучшить производительность сложных запросов. Вместо многократного повторения одних и тех же вложенных подзапросов, мы можем вычислить промежуточный результат один раз, поместить его во временную таблицу и затем многократно к ней обращаться. Это особенно актуально для баз данных с большим объемом данных.

Заключение

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

← На главную