Интернет. Железо. Программы. Обзоры. Операционные системы

Временная таблица в условии запроса 1с. Влияние на производительность

Очень часто это порождает распространенную ошибку — запрос в цикле. То есть разработчик не умеет включать таблицу значений в запрос и поэтому начинает обходить её в цикле и делать на каждую итерацию свой запрос. Рассмотрим на простом примере, как это сделать.

Пример

В качестве примера размещения таблицы значения в запросе 1С 8.3 возьмем простую ситуацию — есть , в которой содержится список номенклатуры. Необходимо получить данные по остаткам на складах по каждой номенклатурной позиции.

Получите 267 видеоуроков по 1С бесплатно:

Может быть две ситуации, как создана таблица значений, — программно и уже получена откуда-то (например, ТЧ документа). Если таблица создана программно, необходимо установить тип колонки , сделать это несложно

Т.е. при добавление колонки необходимо вторым параметром указать типы данных с помощью конструктора объекта «ОписаниеТипов».

Перейдем к построению запроса. Таблицу значений можно передать в запрос простым &Параметром.

Обязательный нюанс — созданную таблицу необходимо поместить результат во временную таблицу, в противном случае система выдаст сообщение: «Ошибка при вызове метода контекста (Выполнить): Содержимое объекта данных может быть выбрано только во временную таблицу ».

Таким образом, мы помещаем первый запрос во временную таблицу, а потом соединяем её с регистром остатков номенклатуры.

Вот и всё, проблема решена.

Язык запросов 1С:Предприятия 8 позволяет использовать временные таблицы в запросах. Использование временных таблиц помогает повысить производительность запросов и сделать текст сложных запросов более легким для восприятия.

Работа с временными таблицами обеспечивается двумя составляющими:

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

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

Экземпляр менеджера временных таблиц может быть создан с помощью конструктора Новый. Например:

Все временные таблицы, созданные в данном экземпляре менеджера, существуют до тех пор, пока существует сам экземпляр менеджера временных таблиц. При уничтожении экземпляра менеджера все временные таблицы, содержащиеся в нем, также удаляются.

Менеджер временных таблиц можно закрыть принудительно при помощи метода Закрыть(). При этом будут удалены все созданные в нем таблицы. Дальнейшая работа с данным экземпляром менеджера будет невозможна.

Создание временных таблиц
Создание временных таблиц осуществляется с помощью объекта Запрос встроенного языка 1С:Предприятия 8.

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

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

Временная таблица может быть создана на основе данных базы данных или на основе внешнего источника данных (например, таблицы значений).

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

ВЫБРАТЬ
Код,
Наименование
ПОМЕСТИТЬ ВременнаяТаблица
ИЗ Справочник.Номенклатура

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

В случае если менеджер временных таблиц не установлен, или менеджер был закрыт, будет выдана ошибка.

В случае если в установленном менеджере временных таблиц уже существует таблица с указанным именем, будет выдана ошибка.

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

Например:

ВЫБРАТЬ
Код,
Наименование
ПОМЕСТИТЬ ВременнаяТаблица
ИЗ Справочник.Номенклатура
ИНДЕКСИРОВАТЬ ПО Код

Поля, по которым происходит индексирование должны находиться в списке выборки.

Для того, чтобы создать временную таблицу и заблокировать данные таблиц, на основании которых создается временная, следует использовать конструкцию ДЛЯ ИЗМЕНЕНИЯ, следует использовать конструкцию ДЛЯ ИЗМЕНЕНИЯ.

Например:

ВЫБРАТЬ
РасходнаяНакладная.Ссылка,
РасходнаяНакладная.Номер,
РасходнаяНакладная.Дата
ПОМЕСТИТЬ ВременнаяТаблица
ИЗ
Документ.РасходнаяНакладная КАК РасходнаяНакладная
ГДЕ
РасходнаяНакладная.Ссылка В(&Документы)

ДЛЯ ИЗМЕНЕНИЯ

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

Таблица значений;
табличная часть;
результат запроса.
Ниже приведен пример создания временной таблицы на основе внешнего источника:

ВЫБРАТЬ
Код,
Наименование
ПОМЕСТИТЬ ВременнаяТаблица
ИЗ &ВнешнийИсточник КАК ВнешнийИсточник

В данном примере во временную таблицу "ВременнаяТаблица" будет помещено содержимое колонок "Код" и "Наименование" из внешнего источника, например, таблицы значений, переданной в качестве параметра "ВнешнийИсточник".

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

Использование временных таблиц
Для использования существующих временных таблиц в запросе следует установить объекту Запрос менеджер временных таблиц, после чего к временным таблицам, содержащимся в данном менеджере временных таблиц, можно обращаться по имени, как к обычным таблицам запроса.

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

УНИЧТОЖИТЬ ВременнаяТаблица

В случае если уничтожаемой таблицы не существует, будет выдана ошибка.

Бывают ситуации когда в одном запросе необходимо объединить несколько запросов, причем соединения таблиц никак не могут в этом помочь. Проще всего показать на примере.

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

Чтобы подсчитать общую задолженность контрагента необходимо сложить сумму всех расходов по этому контрагенту и вычесть сумму всех приходов от этого же контрагента, проще всего это сделать с помощью оператора ОБЪЕДИНИТЬ ВСЕ:

Запрос.Текст =
"
//посчитаем на какую сумму мы отгрузили контрагентам
|ВЫБРАТЬ
| Расход.Контрагент,
|ИЗ
| Документ.Расход КАК Расход
|СГРУППИРОВАТЬ ПО
| Расход.Контрагент
|ОБЪЕДИНИТЬ ВСЕ
//посчитаем на какую сумму контрагенты
//поставили нам товара
|ВЫБРАТЬ
| Приход.Контрагент,
//сумму берем с отрицательным знаком,
//что при объединении она вычлась из суммы расхода
| СУММА(-Приход.Сумма)
|ИЗ
| Документ.Приход КАК Приход
|СГРУППИРОВАТЬ ПО
| Приход.Контрагент";

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

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

Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Расход.Контрагент,
| СУММА(Расход.Сумма) КАК Долг
|ПОМЕСТИТЬ ВТ_ПриходРасход
|ИЗ
| Документ.Расход КАК Расход
|СГРУППИРОВАТЬ ПО
| Расход.Контрагент
|ОБЪЕДИНИТЬ ВСЕ
|ВЫБРАТЬ
| Приход.Контрагент,
| СУММА(-Приход.Сумма)
|ИЗ
| Документ.Приход КАК Приход
|СГРУППИРОВАТЬ ПО
| Приход.Контрагент
|;
|////////////////////////////////////////////////////////////////////////////////
|ВЫБРАТЬ
| ВТ_ПриходРасход.Контрагент,
| СУММА(ВТ_ПриходРасход.Долг) КАК Долг
|ИЗ
| ВТ_ПриходРасход КАК ВТ_ПриходРасход
|СГРУППИРОВАТЬ ПО
| ВТ_ПриходРасход.Контрагент";

Требования к объединению запросов

При объединении двух запросов количество полей у них должно быть одинаковым, если в каком либо из запросов не хватает полей, то их надо добавить в виде констант. Обратимся к примеру выше, пусть в документе расход также есть поле скидка, которое уменьшает сумму долга контрагента, но в документе приход нет никаких скидок. Как быть в этом случае? Так:

Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Расход.Контрагент,

|ИЗ
| Документ.Расход КАК Расход
|СГРУППИРОВАТЬ ПО
| Расход.Контрагент
|ОБЪЕДИНИТЬ ВСЕ
|ВЫБРАТЬ
| Приход.Контрагент,
| СУММА(-Приход.Сумма),
//добавляем нулевое поле скидка
| 0
|ИЗ
| Документ.Приход КАК Приход
|СГРУППИРОВАТЬ ПО
| Приход.Контрагент";

Осталось вычесть скидку и сгруппировать.

Также важен порядок. Поля будут объединятся именно в том порядке в котором они указаны в секциях ВЫБРАТЬ обоих запросов. Применительно к предыдущему примеру - поменяем местами поля скидка и сумма в выборке приходов:

Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Расход.Контрагент,
| СУММА(Расход.Сумма) КАК Долг,
| СУММА(Расход.Скидка) КАК Скидка
|ИЗ
| Документ.Расход КАК Расход
|СГРУППИРОВАТЬ ПО
| Расход.Контрагент
|ОБЪЕДИНИТЬ ВСЕ
|ВЫБРАТЬ
| Приход.Контрагент,
//меняем местами
| 0,
| СУММА(-Приход.Сумма)
|ИЗ
| Документ.Приход КАК Приход
|СГРУППИРОВАТЬ ПО
| Приход.Контрагент";

43
NULL – отсутствующие значения. Не путать с нулевым значением! NULL – это не число, не равно пробелу, пустой ссылке, Неопределено. NULL – типообразующее значение, т.е. есть тип NULL и единственное значение этого типа. NULL... 26
Для формирования и выполнения запросов к таблицам базы данных в платформе 1С используется специальный объект языка программирования Запрос. Создается этот объект вызовом конструкции Новый Запрос. Запрос удобно... 18
В статье приведены полезные приемы при работе с запросами 1С v.8.2, а также сведения, которые не так хорошо известны о языке запросов. Я не стремлюсь дать полное описание языка запросов, а хочу остановиться лишь на... 13
ПОДОБНО - Оператор проверки строки на подобие шаблону. Аналог LIKE в SQL. Оператор ПОДОБНО позволяет сравнить значение выражения, указанного слева от него, со строкой шаблона, указанной справа. Значение выражения...

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

Использование объекта, который носит название «Менеджер временных таблиц» позволяет:

  • Значительно упростить текст запроса;
  • Разбить его на более простые блоки;
  • Увеличить его читаемость и структурированность.

Несколько слов о том, как это работает

В принципе, в работе менеджера временных таблиц можно выделить четыре этапа использования:

  1. Создание менеджера;
  2. Его заполнение;
  3. Чтение данных из таблиц;
  4. Уничтожение менеджера и очистка таблиц.

Давайте поговорим о каждом этапе поподробнее.

Создание менеджера временных таблиц

Для того, чтобы определить этот объект необходимо выполнить код, показанный на Рис.1

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

Рис.2

Заполнение менеджера

На том же рисунке 1 указана строка, которая передает выборку во временную таблицу. Начинается она с оператора «Поместить». В качестве места назначения указывается имя таблицы-приемника.

Используя «Конструктор запроса» эту строку можно создать на закладке «Дополнительно» Рис.3.

Рис.3

Для этого необходимо:

  1. Установить переключатель «Тип запроса» в положение «Создание временной таблицы»;
  2. Указать имя приемника.

Если с помощью отладчика проверить последовательность заполнения менеджера, можно обнаружить, что данные в нем появятся только после исполнения метода запроса Выполнить().

Определить заполненость менеджера можно с помощью оператора Количество(). Пример строки: МВТ.Таблицы.Количество().

Чтение таблиц менеджера

Следующий этап работы – чтение данных из существующих таблиц в другом запросе. Здесь существует одна проблема: новый создаваемый запрос не знает о существовании заполненной таблицы, поэтому в окне «База данных» консоли она не появится.

Её необходимо прописывать и создавать вручную.

Для этого на закладке «Таблицы и поля» (Рис.4) необходимо выполнить некоторую последовательность действий:

Рис.4

  1. В меню окна «Таблицы» этой закладки необходимо нажать кнопку «Создать описание временной таблицы»;
  2. В открывшемся окне необходимо указать наименование поля и его описание (тип поля), как оно задано в существующей таблице;
  3. Необходимые поля или функции с ними нужно перенести в третье окно закладки.

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

Удаление таблиц

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

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

  • Указав непосредственно в тексте запроса ключевое слово Уничтожить;
  • Использовав метод Закрыть(), примененный непосредственно к менеджеру.

Во втором случае будут принудительно уничтожены все таблицы, созданные различными запросами.

Использование первого варианта удаления данных можно прописать явно, записав в тексте запроса строку вида «Уничтожить ИмяТаблицы», либо воспользовавшись закладкой «Дополнительно» (Рис.2) окна «Конструктор запроса».

Переключив переключатель в положение «Уничтожение» и указав имя объекта, который необходимо удалить, Вы без проблем выполните это действие.

Передача (ТЗ) в запрос

Одно из наиболее частых направлений использования этого менеджера – передача в качестве одного из источников данных в запрос таблицы значений. Как известно, непосредственное использование этой коллекции в запросе в 1С не предусмотрено.

Для этого текст запроса должен содержать строку вида «Выбрать * Поместить МВТ из &Тз Как Таб» . Передав в качестве параметра «ТЗ» для запроса существующую таблицу значений мы получим объект, подходящий для дальнейшей обработки в других запросах.

Единственным условием, препятствующим передаче ТЗ в качестве параметра, являются неявно объявленные типы ее колонок. То есть при создании колонок ТЗ необходимо заполнять второй параметр строкой вида «Новый ОписаниеТипов(«»)).

Похожие публикации