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

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

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

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

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

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

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

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

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

Пример создания таблицы с типизированными колонками:

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

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

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

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

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

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

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

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

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

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

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

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

"ВЫБРАТЬ

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

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

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

|ИЗ

| &ТЗ КАК ТЗ";

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

Запрос.Выполнить();

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

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

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

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

"ВЫБРАТЬ

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

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

|ИЗ

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

|ГДЕ

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

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

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

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

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

Условия можно параметризовать: ГДЕ ВТ.Количество >= &МинКоличество. Параметры задаются через УстановитьПараметр до выполнения запроса. Группировка полезна, когда исходная таблица содержит дубли по ключевому полю — например, одна номенклатура встречается в нескольких строках загруженного файла.

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

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

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

Количество строк результата
Норма

Совпадает с ожидаемым числом позиций из исходной таблицы (или меньше — если есть отбор)

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

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

Типы полей результата
Норма

Ссылочные поля содержат ссылки, числовые — числа

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

Поля содержат NULL или строки вместо ссылок

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

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

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

Сумма меньше — часть строк потерялась из-за условий или типов

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

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

"ВЫБРАТЬ

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

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

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

|ИЗ

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

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

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

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

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

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

Отбор по таблице значений без временной таблицы

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

МассивНоменклатуры = ТЗ.ВыгрузитьКолонку("Номенклатура");

Запрос.УстановитьПараметр("Список", МассивНоменклатуры);

// В тексте запроса: ГДЕ Номенклатура В (&Список)

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

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

Временная таблица (ПОМЕСТИТЬ + &ТЗ)

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

Параметр-массив (В (&Список))

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

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

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

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

Большинство проблем при выборке из таблицы значений сводится к нескольким повторяющимся причинам. Знание их экономит часы отладки.

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

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

Для ускорения соединений временную таблицу можно проиндексировать прямо в запросе: ИНДЕКСИРОВАТЬ ПО Номенклатура после секции ПОМЕСТИТЬ. Это особенно заметно, когда временная таблица соединяется с крупными таблицами регистров.

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

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

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

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

Итог

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

Таблица значений попадает в запрос только через параметр и оператор ПОМЕСТИТЬ во временную таблицу. Обязательны типизированные колонки и назначенный МенеджерВременныхТаблиц. Для простого отбора по одному полю достаточно параметра-массива. Результат проверяйте сверкой итогов до и после запроса.

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

Можно ли использовать таблицу значений в запросе без ПОМЕСТИТЬ?

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

Почему запрос возвращает пустой результат, хотя таблица значений заполнена?

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

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

В секции ВЫБРАТЬ из параметра перечислите только нужные поля — остальные колонки просто не попадут во временную таблицу. Либо заранее создайте копию таблицы методом ТЗ.Скопировать() с нужными колонками.

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

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

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

Запросы в 1С предназначены только для чтения. Для записи данные выбираются запросом (в том числе из временной таблицы), а затем в цикле создаются или изменяются объекты и записи регистров средствами встроенного языка.

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

Таблица значений — объект в памяти, который можно редактировать, сортировать и передавать между процедурами. Результат запроса — поток данных только для чтения; чтобы получить редактируемую таблицу, его нужно выгрузить методом Выгрузить().