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