Разработка и Конфигурация · 11 мин
Как сделать запрос к таблице значений в 1С
Как выполнить запрос к таблице значений в 1С: помещение ТЗ во временную таблицу, отбор, группировка и соединение. Примеры кода, ошибки и проверка результата.
Таблица значений в 1С — объект встроенного языка, который живёт только в памяти сеанса. Напрямую обратиться к ней в тексте запроса нельзя: конструктор запроса работает с таблицами базы данных, а ТЗ к ним не относится. Чтобы применить к таблице значений всю мощь языка запросов — отборы, группировки, соединения, итоги — её сначала помещают во временную таблицу с помощью параметра запроса.
Такой приём востребован постоянно: нужно отфильтровать загруженные из Excel строки, свернуть дубли, соединить данные формы с данными регистра, подготовить таблицу для пакетной записи. Без запроса пришлось бы перебирать строки в цикле с вложенными поисками, что на больших объёмах работает на порядки медленнее.
Ниже разобран полный рабочий цикл: подготовка таблицы значений, передача её в запрос через менеджер временных таблиц, фильтрация, группировка, соединение с данными информационной базы, а также типичные ошибки, из-за которых запрос падает или возвращает пустой результат.
Почему нельзя запросить таблицу значений напрямую
Язык запросов 1С исполняется на стороне СУБД и оперирует физическими таблицами информационной базы: справочниками, документами, регистрами. Таблица значений существует только в оперативной памяти сервера или толстого клиента, у неё нет представления в базе данных, поэтому конструктор запроса её «не видит».
Обходной путь стандартный: параметр запроса способен принять таблицу значений целиком. Когда в тексте запроса в качестве источника указан параметр, платформа материализует переданную ТЗ как набор строк, из которого можно построить временную таблицу. Дальше с ней работают обычными средствами языка запросов.
Базовый приём: помещение ТЗ во временную таблицу
Минимальный рабочий шаблон состоит из трёх шагов: создать менеджер временных таблиц, передать таблицу значений параметром, выполнить пакетный запрос из двух частей — создание ВТ и выборка из неё.
Запрос = Новый Запрос;
Запрос.МенеджерВременныхТаблиц = Новый МенеджерВременныхТаблиц;
Запрос.УстановитьПараметр("ТЗ", ТаблицаТоваров);
Запрос.Текст =
"ВЫБРАТЬ
| ТЗ.Номенклатура КАК Номенклатура,
| ТЗ.Количество КАК Количество
|ПОМЕСТИТЬ ВТ_Товары
|ИЗ
| &ТЗ КАК ТЗ
|;
|
|ВЫБРАТЬ
| ВТ.Номенклатура,
| ВТ.Количество
|ИЗ
| ВТ_Товары КАК ВТ
|ГДЕ
| ВТ.Количество > 10";
Результат = Запрос.Выполнить().Выгрузить();
Обратите внимание на детали. Псевдоним источника «ТЗ» и псевдонимы полей обязательны: без явного перечисления полей с псевдонимами платформа не сможет корректно построить временную таблицу. Имена колонок в тексте запроса должны совпадать с именами колонок таблицы значений с точностью до регистра.
Менеджер временных таблиц нужен, если вы планируете обращаться к ВТ в нескольких пакетах или разных запросах подряд. Если временная таблица создаётся и используется внутри одного пакета, менеджер можно не создавать — платформа управит временем жизни сама.
- 1Подготовьте таблицу значений: нужные колонки, корректные типы, без пустых имён колонок
- 2Создайте запрос и при необходимости менеджер временных таблиц
- 3Передайте ТЗ через УстановитьПараметр("ТЗ", ВашаТаблица)
- 4Напишите пакет: ВЫБРАТЬ поля ПОМЕСТИТЬ ВТ ИЗ &ТЗ, затем выборку из ВТ
- 5Выполните запрос и проверьте результат через Выгрузить() или Выбрать()
Требования к таблице значений перед передачей в запрос
Главная причина ошибок — несоответствие состава и типов колонок тому, что ожидает запрос. Перед передачей проверьте три вещи. Во-первых, все колонки, упомянутые в тексте запроса, реально существуют в ТЗ: опечатка в имени даст ошибку «Поле не найдено». Во-вторых, типы колонок должны быть однозначными и совместимыми с операциями: если колонка «Количество» содержит строки, сравнение с числом или суммирование приведёт к ошибке либо к неожиданному результату.
В-третьих, избегайте колонок составного типа «произвольный объект», когда планируете соединение с таблицами базы. Если колонка содержит ссылки разных типов, соединение с конкретным справочником отработает корректно, но при выражении типов через ВЫРАЗИТЬ лучше зафиксировать нужный тип явно — это и быстрее, и предсказуемее.
Если ТЗ собирается программно, задавайте типы колонок при создании через ОписаниеТипов. Это дешёвая страховка: запрос получит строго типизированную временную таблицу, и индексы временных таблиц при соединениях будут работать эффективнее.
Фильтрация и группировка данных таблицы значений
После помещения во временную таблицу к данным применимы все возможности языка запросов. Типовой сценарий — свёртка дублей: ТЗ загружена из файла, одна и та же номенклатура встречается в нескольких строках, нужно получить итоговые количества.
"ВЫБРАТЬ
| ВТ.Номенклатура КАК Номенклатура,
| СУММА(ВТ.Количество) КАК Количество,
| СУММА(ВТ.Сумма) КАК Сумма
|ИЗ
| ВТ_Товары КАК ВТ
|СГРУППИРОВАТЬ ПО
| ВТ.Номенклатура
|УПОРЯДОЧИТЬ ПО
| Номенклатура"
Аналогично решается удаление дублей без агрегации — через ВЫБРАТЬ РАЗЛИЧНЫЕ или группировку по всем ключевым полям. Это заметно удобнее, чем ручной перебор с поиском дублей методом НайтиСтроки: на таблице в десятки тысяч строк разница по времени составляет секунды против минут.
Для фильтрации по списку значений используйте обычное условие В (&СписокЗначений) — параметр списком передаётся так же, как и в запросах к таблицам базы. Временная таблица в этом смысле ничем не ограничена.
Соединение таблицы значений с данными информационной базы
Самый ценный сценарий — соединение ТЗ с реальными таблицами. Например, в таблице значений есть коды товаров из внешнего файла, а нужно подтянуть ссылки номенклатуры, текущие цены или остатки.
"ВЫБРАТЬ
| ВТ.КодТовара КАК КодТовара,
| Ном.Ссылка КАК Номенклатура,
| ЕСТЬNULL(Остатки.КоличествоОстаток, 0) КАК Остаток
|ИЗ
| ВТ_Товары КАК ВТ
| ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Номенклатура КАК Ном
| ПО ВТ.КодТовара = Ном.Код
| ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ТоварыНаСкладах.Остатки КАК Остатки
| ПО Ном.Ссылка = Остатки.Номенклатура"
Левое соединение здесь принципиально: строки ТЗ, для которых не нашлось соответствия в справочнике, не потеряются — в поле ссылки будет NULL, и вы сможете отдельно обработать не найденные позиции. Проверка на NULL через ЕСТЬNULL или условие ЕСТЬ NULL — стандартный способ вычислить строки, которые не удалось сопоставить, и сообщить о них пользователю вместо тихой потери данных.
Если поле связи в ТЗ имеет составной тип или тип отличается от типа поля базы, используйте ВЫРАЗИТЬ(ВТ.КодТовара КАК Строка(20)) в условии соединения. Несовпадение типов — частая причина, когда соединение внешне работает, но возвращает пустые ссылки.
Способы обработки таблицы значений
Подходит для отборов, группировок, соединений с базой и больших объёмов. Требует аккуратности с типами колонок.
Быстро для простых задач на маленьких таблицах: свёртка по паре колонок, поиск одной строки. Не масштабируется на сложную логику.
Гибко, но медленно и трудоёмко. Оправдано только когда к каждой строке нужна сложная нестандартная логика, невыразимая запросом.
Типичные ошибки и их признаки
Ошибка «Поле не найдено» при выполнении — почти всегда опечатка в имени колонки или колонка отсутствует в ТЗ. Проверяйте состав колонок через отладчик или вывод ТЗ в табличный документ перед выполнением запроса.
Пустой результат при внешне корректном запросе чаще всего означает одно из трёх: ТЗ на момент выполнения пуста (например, её заполняют после установки параметра — параметр фиксируется при вызове УстановитьПараметр), не совпадают типы полей соединения, либо условие отбора отсекает всё из-за различий в представлении данных (лишние пробелы, регистр символов в строковых кодах).
Ещё одна ловушка — повторное использование имени временной таблицы. Если в том же менеджере временных таблиц уже существует ВТ с таким именем, запрос упадёт с ошибкой. Либо давайте уникальные имена, либо явно уничтожайте таблицу командой УНИЧТОЖИТЬ ВТ_Товары между пакетами.
Проверка результата и производительность
После выполнения запроса сверьте количество строк результата с ожиданием: при левом соединении оно не должно быть меньше числа уникальных ключей ТЗ. Если строк больше, чем строк в исходной таблице, — соединение размножило строки, значит, ключ связи не уникален со стороны базы (например, дубли кодов в справочнике).
По производительности: передача ТЗ параметром — это физическая загрузка данных во временное хранилище СУБД. Таблицы в десятки тысяч строк обрабатываются комфортно; при сотнях тысяч строк стоит оценить, нельзя ли получить те же данные сразу запросом к базе, минуя промежуточную ТЗ. Для очень больших загрузок из файлов иногда эффективнее порционная обработка пачками.
Как проверить результат
Равно ожидаемому количеству после группировки или соединения
Строк больше, чем в ТЗ — дубли ключа соединения; меньше — потеряны строки из-за внутреннего соединения
Заполнены для всех существующих в базе ключей
Массовые NULL при заведомо существующих элементах — несовпадение типов или форматов ключей
Суммы по сгруппированным данным совпадают с итогом исходной ТЗ
Расхождение — потеряны строки или ошибка в условии отбора
FAQ
Можно ли передать в запрос таблицу значений с формы?
Да. Коллекцию данных формы сначала выгружают в таблицу значений методом Выгрузить(), полученную ТЗ передают параметром как обычно. Учтите, что в выгрузку попадут только колонки данных, без служебных колонок формы.
Нужен ли менеджер временных таблиц всегда?
Нет. Если временная таблица создаётся и используется внутри одного пакетного запроса, менеджер можно не создавать. Он обязателен, когда к одной и той же ВТ обращаются из нескольких отдельных запросов — тогда менеджер связывает их в общий контекст.
Как удалить дубли строк в таблице значений запросом?
Поместите ТЗ во временную таблицу и выполните ВЫБРАТЬ РАЗЛИЧНЫЕ по нужным колонкам, либо сгруппируйте по ключевым полям с агрегатными функциями для числовых колонок. Результат выгрузите обратно в таблицу значений.
Почему соединение с справочником возвращает пустые ссылки, хотя элементы существуют?
Чаще всего не совпадают типы или форматы полей связи: в ТЗ код хранится как число, а в справочнике — как строка, либо в строках есть неразрывные пробелы из файла загрузки. Приведите типы через ВЫРАЗИТЬ и очистите строки перед загрузкой в ТЗ.
Есть ли ограничение на размер передаваемой таблицы значений?
Жёсткого лимита платформа не задаёт, но таблица целиком материализуется во временном хранилище. На практике десятки тысяч строк работают стабильно; при сотнях тысяч стоит замерить время и рассмотреть порционную обработку или прямой запрос к базе.
Можно ли обновить исходную таблицу значений результатом запроса?
Да: результат запроса выгружается методом Выгрузить() в новую таблицу значений, которую можно присвоить вместо старой или загрузить обратно в реквизит формы методом Загрузить(). Исходная ТЗ при этом сама не изменяется — запрос только читает её.
Что важно запомнить
Запрос к таблице значений выполняется через временную таблицу: ТЗ передаётся параметром, материализуется конструкцией ПОМЕСТИТЬ ВТ и дальше обрабатывается полноценным языком запросов. Контролируйте типы колонок, используйте левые соединения с базой и проверяйте число строк результата — это покрывает почти все ошибки на практике.