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

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

Как использовать таблицу значений в запросе 1С

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

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

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

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

Когда таблицу значений стоит передавать в запрос

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

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

Маршрут решения

Как выбрать подход

Нужно отобрать по одному полю (список ссылок, артикулов)Используйте параметр-массив и условие В (&Параметр) — таблица значений не нужна
Нужно соединение по нескольким колонкам или данные получены из файла/расчётаПередавайте таблицу значений параметром и помещайте во временную таблицу
Данные нужны только для одного простого условияОбычный параметр запроса проще и читаемее

Подготовка таблицы значений: колонки и типы

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

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

bsl
ОписаниеСтроки = Новый ОписаниеТипов("Строка", , Новый КвалификаторыСтроки(50));
ОписаниеСсылки = Новый ОписаниеТипов("СправочникСсылка.Номенклатура");

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

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

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

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

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

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

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

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

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

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

Внутреннее соединение вернёт только совпавшие строки — подходит, когда не найденные в базе позиции не нужны. Левое соединение сохранит все строки вашей таблицы значений, а для ненайденных соответствий поля базы будут NULL — так удобно строить отчёт об ошибках загрузки: «артикул есть в файле, но не найден в справочнике».

При соединении по строковым полям учитывайте регистр и пробелы: «АРТ-001» и «арт-001 » в левом соединении не совпадут. Если данные приходят из внешних файлов, предварительно нормализуйте их в коде — обрежьте пробелы функцией СокрЛП и при необходимости приведите регистр.

Частая ситуация: соединение по наименованию или артикулу «не находит» очевидно существующие записи. В большинстве случаев причина — неразрывные пробелы или невидимые символы в загруженных из Excel данных. Проверяйте длину строки функцией СтрДлина — она быстро показывает лишние символы.
ПЗ
Практическое замечание

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

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

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

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

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

Количество строк во временной таблице
Норма

Совпадает с числом строк исходной таблицы значений

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

Строк меньше или таблица пуста — проверяйте типы колонок и параметр

Результат соединения
Норма

Число строк ожидаемое, ключевые поля заполнены

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

Лишние строки (дубли) или NULL там, где ожидались данные

Итоговые суммы после группировки
Норма

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

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

Суммы завышены — вероятно, дубли в условиях соединения

Ограничения и альтернативные подходы

Передача таблицы значений в запрос имеет ограничения. Во временную таблицу нельзя выгрузить колонки с типом ХранилищеЗначения или с неограниченным составом типов — такие поля придётся исключить или преобразовать. Также нельзя передать таблицу значений в запрос, выполняемый в СКД напрямую через набор данных-запрос без обходных приёмов; там используют набор данных-объект.

Альтернативы стоит знать. Для отбора по одному полю — параметр-массив. Для данных, которые уже есть в базе, — прямой запрос без таблицы значений. Для очень больших объёмов — внешние источники данных или пакетная загрузка порциями. Для СКД — набор данных «Объект» с именем объекта, переданным через параметр.

Сравнение подходов

Таблица значений как параметр

Универсально: несколько колонок, любые данные из кода. Ограничение — объём и обязательная типизация колонок

Параметр-массив с условием В()

Проще и быстрее для отбора по одному полю. Не подходит для соединения по нескольким колонкам

Набор данных-объект в СКД

Единственный штатный способ передать таблицу значений в схему компоновки данных

Перебор строк с запросом в цикле

Просто в реализации, но медленно при большом числе строк — использовать только для единичных обращений

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

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

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

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

Итог

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

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

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

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

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

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

Чаще всего типы полей в соединении несовместимы: например, колонка таблицы значений имеет составной тип, а поле базы — конкретный. Задайте колонке точный тип через ОписаниеТипов или приведите тип в запросе функцией ВЫРАЗИТЬ.

Как передать таблицу значений в отчёт на СКД?

Через параметр напрямую нельзя. Используйте набор данных типа «Объект»: в схеме компоновки укажите имя объекта, а в коде при формировании отчёта передайте таблицу значений в процессор компоновки через объект внешних наборов данных.

Есть ли ограничение на количество строк в передаваемой таблице?

Жёсткого ограничения платформа не накладывает, но при очень больших объёмах растут расход памяти и время выгрузки во временную таблицу. На практике таблицы в десятки тысяч строк работают нормально; при сотнях тысяч строк лучше разбивать обработку на порции.

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

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

Почему соединение не находит записи, хотя данные совпадают?

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