При отладке сложных запросов и разделении их на составные части разработчики часто сталкиваются с ситуацией, когда прямой запрос к таблице или регистру возвращает данные, а при попытке поместить эти же данные во временную таблицу консоль запросов показывает пустой результат. Разберем подробно, как работает механизм временных таблиц платформы 1С, почему возникает такая ситуация и как правильно организовать пакетные запросы.
Проанализируем базовый запрос выборки данных из виртуальной таблицы остатков регистра накопления:
ВЫБРАТЬ
ЗаказыОстатки.ЗаказКлиента КАК ЗаказКлиента,
ЗаказыОстатки.Номенклатура КАК Номенклатура,
ЗаказыОстатки.Характеристика КАК Характеристика,
ЗаказыОстатки.КодСтроки КАК КодСтроки,
ЗаказыОстатки.Склад КАК Склад,
ЗаказыОстатки.КОформлениюОстаток КАК КОформлению,
ЗаказыОстатки.СуммаОстаток КАК Сумма
ИЗ
РегистрНакопления.ЗаказыКлиентов.Остатки(, ЗаказКлиента = &МассивЗаказов) КАК ЗаказыОстатки
Этот запрос возвращает стандартную таблицу результатов. Однако если мы добавляем конструкцию ПОМЕСТИТЬ, поведение платформы кардинально меняется:
ВЫБРАТЬ
ТаблицаЗаказы.ЗаказКлиента КАК ЗаказКлиента,
ТаблицаЗаказы.Номенклатура КАК Номенклатура
ПОМЕСТИТЬ ТаблицаОстатки
ИЗ
(ВЫБРАТЬ
ЗаказыОстатки.ЗаказКлиента КАК ЗаказКлиента,
ЗаказыОстатки.Номенклатура КАК Номенклатура,
ЗаказыОстатки.Характеристика КАК Характеристика,
ЗаказыОстатки.КодСтроки КАК КодСтроки,
ЗаказыОстатки.Склад КАК Склад,
ЗаказыОстатки.КОформлениюОстаток КАК КОформлению,
ЗаказыОстатки.СуммаОстаток КАК Сумма
ИЗ
РегистрНакопления.ЗаказыКлиентов.Остатки(, ЗаказКлиента = &МассивЗаказов) КАК ЗаказыОстатки) КАК ТаблицаЗаказы
Выясним причину, почему во втором случае результат кажется пустым:
ПОМЕСТИТЬ создает временную таблицу на стороне СУБД (например, в базе данных tempdb для MS SQL Server). Данные успешно записываются во временную таблицу, но не возвращаются в клиентское приложение в виде выборки строк.Запрос.ВыполнитьПакет() шагу с оператором ПОМЕСТИТЬ соответствует пустой результат (или техническая строка со служебной информацией). Обычные консоли запросов не умеют отображать содержимое промежуточных временных таблиц, если нет явного завершающего запроса на чтение.Для того чтобы проверить содержимое созданной временной таблицы, необходимо использовать пакетный запрос с разделителем точка с запятой (;) и завершающей выборкой из созданной таблицы. Кроме того, создание избыточных вложенных запросов вокруг виртуальной таблицы является неоптимальным подходом.
Посмотрим на корректную и оптимизированную структуру пакетного запроса:
ВЫБРАТЬ
ЗаказыОстатки.ЗаказКлиента КАК ЗаказКлиента,
ЗаказыОстатки.Номенклатура КАК Номенклатура,
ЗаказыОстатки.Характеристика КАК Характеристика,
ЗаказыОстатки.КодСтроки КАК КодСтроки,
ЗаказыОстатки.Склад КАК Склад,
ЗаказыОстатки.КОформлениюОстаток КАК КОформлению,
ЗаказыОстатки.СуммаОстаток КАК Сумма
ПОМЕСТИТЬ ТаблицаОстатки
ИЗ
РегистрНакопления.ЗаказыКлиентов.Остатки(, ЗаказКлиента = &МассивЗаказов) КАК ЗаказыОстатки
;
ВЫБРАТЬ
ТаблицаОстатки.ЗаказКлиента КАК ЗаказКлиента,
ТаблицаОстатки.Номенклатура КАК Номенклатура
ИЗ
ТаблицаОстатки КАК ТаблицаОстатки
В таком виде консоль запросов выполнит первый шаг (сохранение в ТаблицаОстатки) и отобразит результат второго шага (выборка полей ЗаказКлиента и Номенклатура).
Еще одной распространенной причиной отсутствия строк является некорректная передача типов в параметры виртуальной таблицы. Разберем по шагам правила работы с условиями:
&МассивЗаказов), но в коде передается массив или список значений, условие со знаком равенства ЗаказКлиента = &МассивЗаказов вернет пустой результат или вызовет ошибку несовместимости типов. Для коллекций обязательно используется оператор В (&МассивЗаказов).=, тип значения в параметре должен строго соответствовать типу измерения (например, ДокументСсылка.ЗаказКлиента).РегистрНакопления.ЗаказыКлиентов.Остатки(, ...)), а не через секцию ГДЕ. Это позволяет СУБД отсекать лишние записи на этапе чтения итогов, существенно снижая нагрузку на систему.При использовании временных таблиц в рабочем коде 1С следует придерживаться следующих правил:
ЛЕВОЕ СОЕДИНЕНИЕ или ВНУТРЕННЕЕ СОЕДИНЕНИЕ), добавляйте секцию ИНДЕКСИРОВАТЬ ПО с указанием ключевых полей. Это предотвратит полное сканирование таблицы СУБД.МенеджерВременныхТаблиц, не забывайте удалять временные таблицы конструкцией УНИЧТОЖИТЬ ИмяТаблицы в конце пакета, чтобы предотвратить неконтролируемый рост базы данных tempdb.