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

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

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

Как выполнить запрос к таблице значений в 1С: помещение ТЗ во временную таблицу, отбор, группировка и соединение. Примеры кода, ошибки и проверка результата.

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

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

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

Почему нельзя запросить таблицу значений напрямую

Язык запросов 1С исполняется на стороне СУБД и оперирует физическими таблицами информационной базы: справочниками, документами, регистрами. Таблица значений существует только в оперативной памяти сервера или толстого клиента, у неё нет представления в базе данных, поэтому конструктор запроса её «не видит».

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

Базовый приём: помещение ТЗ во временную таблицу

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

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

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

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

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

"ВЫБРАТЬ

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

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

|ПОМЕСТИТЬ ВТ_Товары

|ИЗ

| &ТЗ КАК ТЗ

|;

|

|ВЫБРАТЬ

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

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

|ИЗ

| ВТ_Товары КАК ВТ

|ГДЕ

| ВТ.Количество > 10";

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

Обратите внимание на детали. Псевдоним источника «ТЗ» и псевдонимы полей обязательны: без явного перечисления полей с псевдонимами платформа не сможет корректно построить временную таблицу. Имена колонок в тексте запроса должны совпадать с именами колонок таблицы значений с точностью до регистра.

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

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

Требования к таблице значений перед передачей в запрос

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

В-третьих, избегайте колонок составного типа «произвольный объект», когда планируете соединение с таблицами базы. Если колонка содержит ссылки разных типов, соединение с конкретным справочником отработает корректно, но при выражении типов через ВЫРАЗИТЬ лучше зафиксировать нужный тип явно — это и быстрее, и предсказуемее.

Если ТЗ собирается программно, задавайте типы колонок при создании через ОписаниеТипов. Это дешёвая страховка: запрос получит строго типизированную временную таблицу, и индексы временных таблиц при соединениях будут работать эффективнее.

Фильтрация и группировка данных таблицы значений

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

"ВЫБРАТЬ

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

| СУММА(ВТ.Количество) КАК Количество,

| СУММА(ВТ.Сумма) КАК Сумма

|ИЗ

| ВТ_Товары КАК ВТ

|СГРУППИРОВАТЬ ПО

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

|УПОРЯДОЧИТЬ ПО

| Номенклатура"

Аналогично решается удаление дублей без агрегации — через ВЫБРАТЬ РАЗЛИЧНЫЕ или группировку по всем ключевым полям. Это заметно удобнее, чем ручной перебор с поиском дублей методом НайтиСтроки: на таблице в десятки тысяч строк разница по времени составляет секунды против минут.

Для фильтрации по списку значений используйте обычное условие В (&СписокЗначений) — параметр списком передаётся так же, как и в запросах к таблицам базы. Временная таблица в этом смысле ничем не ограничена.

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

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

"ВЫБРАТЬ

| ВТ.КодТовара КАК КодТовара,

| Ном.Ссылка КАК Номенклатура,

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

|ИЗ

| ВТ_Товары КАК ВТ

| ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Номенклатура КАК Ном

| ПО ВТ.КодТовара = Ном.Код

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

| ПО Ном.Ссылка = Остатки.Номенклатура"

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

Если поле связи в ТЗ имеет составной тип или тип отличается от типа поля базы, используйте ВЫРАЗИТЬ(ВТ.КодТовара КАК Строка(20)) в условии соединения. Несовпадение типов — частая причина, когда соединение внешне работает, но возвращает пустые ссылки.

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

Запрос через временную таблицу

Подходит для отборов, группировок, соединений с базой и больших объёмов. Требует аккуратности с типами колонок.

Методы Найти, НайтиСтроки, Свернуть

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

Перебор в цикле

Гибко, но медленно и трудоёмко. Оправдано только когда к каждой строке нужна сложная нестандартная логика, невыразимая запросом.

Типичные ошибки и их признаки

Ошибка «Поле не найдено» при выполнении — почти всегда опечатка в имени колонки или колонка отсутствует в ТЗ. Проверяйте состав колонок через отладчик или вывод ТЗ в табличный документ перед выполнением запроса.

Пустой результат при внешне корректном запросе чаще всего означает одно из трёх: ТЗ на момент выполнения пуста (например, её заполняют после установки параметра — параметр фиксируется при вызове УстановитьПараметр), не совпадают типы полей соединения, либо условие отбора отсекает всё из-за различий в представлении данных (лишние пробелы, регистр символов в строковых кодах).

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

Типичные ошибки
01
Передача ТЗ с нетипизированными колонками — сравнения и суммирование падают или дают неверный результат
02
Установка параметра до заполнения таблицы — запрос получает пустую ТЗ
03
Внутреннее соединение вместо левого — строки без соответствия в базе молча теряются
04
Повторное имя временной таблицы в одном менеджере — ошибка выполнения пакета
05
Опечатка в имени колонки в тексте запроса — ошибка 'Поле не найдено'

Проверка результата и производительность

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

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

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

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

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

Равно ожидаемому количеству после группировки или соединения

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

Строк больше, чем в ТЗ — дубли ключа соединения; меньше — потеряны строки из-за внутреннего соединения

Поля ссылок после соединения
Норма

Заполнены для всех существующих в базе ключей

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

Массовые NULL при заведомо существующих элементах — несовпадение типов или форматов ключей

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

Суммы по сгруппированным данным совпадают с итогом исходной ТЗ

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

Расхождение — потеряны строки или ошибка в условии отбора

FAQ

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

Да. Коллекцию данных формы сначала выгружают в таблицу значений методом Выгрузить(), полученную ТЗ передают параметром как обычно. Учтите, что в выгрузку попадут только колонки данных, без служебных колонок формы.

Нужен ли менеджер временных таблиц всегда?

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

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

Поместите ТЗ во временную таблицу и выполните ВЫБРАТЬ РАЗЛИЧНЫЕ по нужным колонкам, либо сгруппируйте по ключевым полям с агрегатными функциями для числовых колонок. Результат выгрузите обратно в таблицу значений.

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

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

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

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

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

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

Итог

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

Запрос к таблице значений выполняется через временную таблицу: ТЗ передаётся параметром, материализуется конструкцией ПОМЕСТИТЬ ВТ и дальше обрабатывается полноценным языком запросов. Контролируйте типы колонок, используйте левые соединения с базой и проверяйте число строк результата — это покрывает почти все ошибки на практике.