Почему в запросе 1С используется таблица, которая в нем не создается? Разбираем магию Менеджера временных таблиц

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

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

Анализируем исходную проблему

Представим, что мы анализируем модуль менеджера документа и видим пакетный запрос, состоящий из нескольких частей. В одной из них мы встречаем такой код:


|ВЫБРАТЬ
|    Реквизиты.Дата КАК Период,
|    Реквизиты.Ссылка КАК Регистратор,
|    ...
|ИЗ
|    Документ.ПриходныйКассовыйОрдер КАК Реквизиты
|ГДЕ
|    Реквизиты.Ссылка = &Ссылка
|;
|
|ВЫБРАТЬ
|    1 КАК НомерСтроки,
|    Реквизиты.СчетУчетаРасчетовСКонтрагентом КАК СчетКт,
|    ...
|    Реквизиты.ПодразделениеОрганизации КАК ПодразделениеДт,
|    Реквизиты.СуммаДокумента КАК ВалютнаяСумма
|ИЗ
|    <strong>Реквизиты КАК Реквизиты</strong>

Первый запрос в пакете вполне понятен: он выбирает данные из документа ПриходныйКассовыйОрдер. Но второй запрос вызывает недоумение. В секции ИЗ используется источник Реквизиты. Это не физическая таблица базы данных и не временная таблица, созданная с помощью инструкции ПОМЕСТИТЬ в этом же пакете. Как же платформа "понимает", откуда брать данные? Кажется, что это ошибка, но код работает. Выясним причину.

Ключевая роль Менеджера временных таблиц (МВТ)

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

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


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

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

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

Поиск "потерянного" кода с инструкцией ПОМЕСТИТЬ

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

В нашем примере, как выяснилось в ходе анализа, перед формированием "загадочного" запроса вызывалась другая функция, например, ПодготовитьПараметрыРеквизитыДокумента, в которой и содержался "недостающий" фрагмент:


|ВЫБРАТЬ
|    Реквизиты.Дата КАК Дата,
|    Реквизиты.Ссылка КАК Ссылка,
|    Реквизиты.ВидОперации КАК ВидОперации,
|    ...
|<strong>ПОМЕСТИТЬ Реквизиты</strong>
|ИЗ
|    Документ.ПриходныйКассовыйОрдер КАК Реквизиты
|ГДЕ
|    Реквизиты.Ссылка = &Ссылка

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

Таким образом, "магия" развеяна. Это стандартный и очень мощный механизм платформы 1С.

Как это работает вместе: полная картина

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

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

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

Возникает логичный вопрос: что произойдет, если после создания временной таблицы другой пользователь изменит данные в исходной таблице (в нашем примере, в документе ПриходныйКассовыйОрдер)?

Данные во временной таблице не изменятся. МВТ обеспечивает полную изоляцию данных на уровне сеанса. Временная таблица — это "снимок" (snapshot) данных на момент выполнения запроса с инструкцией ПОМЕСТИТЬ. Любые последующие изменения в исходных физических таблицах, сделанные в других сеансах, никак не повлияют на уже созданную ВТ в текущем сеансе. Это гарантирует консистентность и предсказуемость расчетов на протяжении всего выполнения сложного алгоритма.

Практический совет

Если вы столкнулись с подобной "магией" и не можете понять, откуда в запросе взялась та или иная таблица, лучшим способом решения будет глобальный поиск по конфигурации. Просто поищите строку ПОМЕСТИТЬ ИмяТаблицы (например, ПОМЕСТИТЬ Реквизиты). Это поможет вам быстро найти место, где временная таблица была создана, и восстановить полную логику работы кода.

← На главную