К статье
Практический материал

Разработка и Конфигурация · 10 мин

Как добавить таблицу в запрос 1С

Как добавить таблицу значений в запрос 1С через параметр, поместить её во временную таблицу, соединить с данными базы и избежать типичных ошибок при работе.

В языке запросов 1С нельзя напрямую вставить произвольный набор строк, подготовленный в коде. Чтобы использовать такие данные в выборке, таблицу значений передают в запрос как параметр, а затем помещают во временную таблицу через конструкцию ПОМЕСТИТЬ. Это стандартный и самый производительный способ соединить «внешние» данные с данными информационной базы.

Типовые сценарии, где это нужно: фильтрация документов по списку ссылок, загруженному из файла; сопоставление номенклатуры с данными из Excel; расчёт по таблице, собранной алгоритмом в коде; передача результата одного запроса в другой без повторного обращения к базе. Во всех этих случаях механизм одинаковый — отличается только содержимое передаваемой таблицы.

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

Какой механизм использовать и почему

В языке запросов 1С источником данных может быть либо таблица базы данных, либо параметр-таблица, переданный из кода. Прямой вставки строк в текст запроса не существует — язык не поддерживает конструкторы значений наподобие VALUES в чистом SQL. Поэтому единственный корректный путь — параметр типа «ТаблицаЗначений».

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

Шаг 1. Подготовьте таблицу значений в коде

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

ТЗ = Новый ТаблицаЗначений;

ТЗ.Колонки.Добавить("Номенклатура", Новый ОписаниеТипов("СправочникСсылка.Номенклатура"));

ТЗ.Колонки.Добавить("Количество", Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(15, 3)));

НоваяСтрока = ТЗ.Добавить();

НоваяСтрока.Номенклатура = СсылкаНаТовар;

НоваяСтрока.Количество = 10;

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

Шаг 2. Передайте таблицу параметром и поместите во временную таблицу

Таблица передаётся методом УстановитьПараметр, а в тексте запроса к ней обращаются через амперсанд: &ТЗ. Первый запрос пакета выбирает данные из параметра и помещает их во временную таблицу.

Запрос = Новый Запрос;

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

Запрос.УстановитьПараметр("ТЗ", ТЗ);

Запрос.Текст =

"ВЫБРАТЬ

| ТЗ.Номенклатура КАК Номенклатура,

| ТЗ.Количество КАК Количество

|ПОМЕСТИТЬ ВТ_Данные

|ИЗ

| &ТЗ КАК ТЗ

|;

|

|ВЫБРАТЬ

| ВТ.Номенклатура КАК Номенклатура,

| ВТ.Количество КАК Количество,

| ЕСТЬNULL(Остатки.КоличествоОстаток, 0) КАК Остаток

|ИЗ

| ВТ_Данные КАК ВТ

| ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ТоварыНаСкладах.Остатки КАК Остатки

| ПО ВТ.Номенклатура = Остатки.Номенклатура";

Результат = Запрос.Выполнить().Выгрузить();

Обратите внимание: менеджер временных таблиц нужно создать явно, если временная таблица используется более чем в одном запросе пакета или должна жить между вызовами. Без менеджера временная таблица не сохранится.

Порядок действий
  1. 1
    Создайте ТаблицаЗначений и типизируйте колонки через ОписаниеТипов
  2. 2
    Заполните таблицу строками в коде
  3. 3
    Создайте Запрос и назначьте МенеджерВременныхТаблиц
  4. 4
    Передайте таблицу: Запрос.УстановитьПараметр("ТЗ", ТЗ)
  5. 5
    Напишите запрос: ВЫБРАТЬ ... ПОМЕСТИТЬ ВТ_Данные ИЗ &ТЗ КАК ТЗ
  6. 6
    Соедините временную таблицу с таблицами базы
  7. 7
    Выполните запрос и проверьте число строк результата

Шаг 3. Соедините временную таблицу с данными базы

Чаще всего используется ЛЕВОЕ СОЕДИНЕНИЕ: временная таблица слева, таблица базы справа. Тогда в результат попадут все строки переданной таблицы, даже если в базе соответствий нет — поля из базы будут NULL, что удобно обрабатывать функцией ЕСТЬNULL.

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

ТЗ.Свернуть("Номенклатура", "Количество");

Условия по полям временной таблицы (секция ГДЕ) работают так же, как с обычными таблицами. Можно фильтровать, группировать и сортировать — временная таблица полноценный источник данных внутри пакета запросов.

Сравнение вариантов

Параметр + ПОМЕСТИТЬ во временную таблицу

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

Параметр напрямую в соединении

Подходит для разового простого запроса. Меньше кода, но нет индекса по таблице и повторного использования.

Отбор через В (список значений)

Подходит, если нужно только отфильтровать по списку ссылок без дополнительных полей. Не подходит, когда к каждой строке привязаны свои числа или строки.

Проверка результата и контрольные точки

После выполнения запроса сверьте количество строк результата с количеством строк исходной таблицы. При левом соединении строк не должно стать меньше; если стало больше — в данных есть дубли ключей. Для отладки удобно выполнить отдельный запрос ВЫБРАТЬ * ИЗ ВТ_Данные и убедиться, что временная таблица наполнилась ожидаемо.

Контрольные точки

Как проверить результат

Число строк результата
Норма

Равно числу строк исходной ТЗ (при левом соединении)

Тревожный признак

Меньше — потеряны строки; больше — дубли ключей

Поля ссылочного типа
Норма

Заполнены ссылками нужного типа

Тревожный признак

NULL или пустые ссылки — проблема типизации колонки

Числовые поля
Норма

Суммы и количества совпадают с исходными

Тревожный признак

Округление или NULL — неверный тип колонки

Типичные ошибки и ограничения

Первая частая ошибка — обращение к параметру &ТЗ в соединении без помещения во временную таблицу при сложном пакете: запрос может работать медленно, потому что платформа не строит индекс по параметру. Вторая — неявная типизация: колонка, заполненная значениями разных типов, приводит к ошибке выполнения или тихой потере строк.

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

Типичные ошибки
01
Колонка без типа или со смешанными типами — ошибка выполнения запроса или потеря строк
02
Нет МенеджерВременныхТаблиц — «таблица не найдена» при повторном использовании ВТ
03
Дубли ключей в ТЗ — размножение строк результата после соединения
04
Передача огромной таблицы одним куском — рост потребления памяти и времени выполнения
05
Составной тип ссылки без необходимости — замедление соединения и лишние проверки типов

Альтернативы и смежные приёмы

Если нужно только отфильтровать выборку по списку ссылок, передавать таблицу не обязательно — достаточно параметра со списком значений и условия ГДЕ Ссылка В (&Список). Это проще и быстрее, чем полноценная временная таблица.

Если данные уже находятся в результате другого запроса, не выгружайте их в таблицу значений и не передавайте обратно — поместите результат первого запроса во временную таблицу через тот же менеджер и используйте её во втором запросе. Так данные не покидают сервер и не тратится время на сериализацию.

Для обмена с внешними источниками (Excel, CSV) сначала загрузите файл в таблицу значений штатными средствами или через ПостроительЗапроса, а дальше действуйте по описанной выше схеме — механизм не меняется.

Итог

Что важно запомнить

Таблица значений попадает в запрос только через параметр: УстановитьПараметр + ВЫБРАТЬ ... ПОМЕСТИТЬ ВТ ИЗ &ТЗ. Типизируйте колонки, сворачивайте дубли, назначайте менеджер временных таблиц и проверяйте число строк результата после соединения.

Частые вопросы

Можно ли передать в запрос табличную часть документа?

Да. Вызовите у табличной части метод Выгрузить() — получите таблицу значений, которую передаёте параметром обычным способом. При необходимости ограничьте набор колонок через Выгрузить(Новый Структура(...)) или сверните данные перед передачей.

Почему запрос выдаёт ошибку «Неверные параметры в операции сравнения»?

Обычно причина в несовпадении типов: поле временной таблицы сравнивается с полем другого типа или колонка таблицы значений содержит значения разных типов. Проверьте описание типов колонки и приведите значения к одному типу до передачи.

Нужно ли уничтожать временную таблицу после использования?

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

Можно ли передать в запрос дерево значений?

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

Что быстрее: соединение с временной таблицей или условие В (&Список)?

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

Работает ли передача таблицы в запрос в тонком клиенте?

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