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

Дата: 21.09.2026 07:06:43
Запросы
Язык запросов
Таблица значений
Временные таблицы
Встроенный язык
Комментарий:
0
Платформа:
8.3
Конфигурация:
Любая
Формы:
Любые

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

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

Какие таблицы запроса 1С бывают

ИсточникКак пишется после ИЗЧто важно
Объектная таблицаСправочник.НоменклатураДанные базы, у ссылочных полей доступны реквизиты через точку
Табличная частьДокумент.РеализацияТоваровУслуг.ТоварыЕсть поля Ссылка (владелец) и НомерСтроки
Виртуальная таблица регистраРегистрСведений.КурсыВалют.СрезПоследних(&Дата)Отбор лучше передавать в параметрах таблицы, а не в ГДЕ
Временная таблицаВТТовары (создана через ПОМЕСТИТЬ)Живёт в пределах пакета или менеджера временных таблиц, её можно индексировать
Вложенный запрос(ВЫБРАТЬ …) КАК ТВ соединениях с большими таблицами лучше заменить временной
Таблица значений из параметра&ДанныеФайла КАК ДанныеФайлаИспользуется как источник для ПОМЕСТИТЬ, колонки обязательно с типами

Дальше — о двух последних строках таблицы. Общий синтаксис пакетов, соединений и группировок разобран в статье про язык запросов 1С с примерами.

Таблица значений в запросе 1С: схема из трёх шагов

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

Всё это выполняется на сервере. На тонком и веб-клиенте нет ни объекта Запрос, ни ТаблицаЗначений, поэтому в модуле формы код выносят в процедуру с директивой &НаСервере, а в общем модуле ставят флаг «Сервер».

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

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

Тип колонки задаётся вторым параметром Колонки.Добавить. Для ссылок — Новый ОписаниеТипов("СправочникСсылка.Номенклатура"), для чисел — с КвалификаторыЧисла, для строк — обязательно с КвалификаторыСтроки и конкретной длиной. Строка без квалификатора становится строкой неограниченной длины, а такие поля нельзя сравнивать в условии соединения, группировать и упорядочивать.

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

// Возвращает копию таблицы значений, в которой у каждой колонки задан тип.
// Колонкам без типа он собирается по фактическим значениям;
// строки в таких колонках при копировании обрезаются до 150 символов.
Функция ТаблицаСТипизированнымиКолонками(Исходная) Экспорт

	Результат = Новый ТаблицаЗначений;
	Для Каждого Колонка Из Исходная.Колонки Цикл
		ТипКолонки = Колонка.ТипЗначения;
		Если ТипКолонки.Типы().Количество() = 0 Тогда
			ТипКолонки = ТипПоЗначениямКолонки(Исходная, Колонка.Имя);
		КонецЕсли;
		Результат.Колонки.Добавить(Колонка.Имя, ТипКолонки);
	КонецЦикла;

	Для Каждого СтрокаИсходной Из Исходная Цикл
		ЗаполнитьЗначенияСвойств(Результат.Добавить(), СтрокаИсходной);
	КонецЦикла;

	Возврат Результат;

КонецФункции

Функция ТипПоЗначениямКолонки(Таблица, ИмяКолонки)

	Типы = Новый Массив;
	Для Каждого Значение Из Таблица.ВыгрузитьКолонку(ИмяКолонки) Цикл
		ТекущийТип = ТипЗнч(Значение);
		Если ТекущийТип = Тип("Неопределено") Или ТекущийТип = Тип("Null") Тогда
			Продолжить;
		КонецЕсли;
		Если Типы.Найти(ТекущийТип) = Неопределено Тогда
			Типы.Добавить(ТекущийТип);
		КонецЕсли;
	КонецЦикла;

	Если Типы.Количество() = 0 Тогда
		Типы.Добавить(Тип("Строка")); // колонка пустая: тип любой, лишь бы был задан
	КонецЕсли;

	// Длину строки ограничиваем, чтобы по колонке можно было соединять и группировать.
	Возврат Новый ОписаниеТипов(Типы, , Новый КвалификаторыСтроки(150));

КонецФункции

Где тип колонки задан, функция берёт его как есть, где нет — собирает составной тип по значениям, пропуская Неопределено и Null. Колонку, объявленную как ОписаниеТипов("Строка") без длины, она не исправит: такую создайте заново с квалификатором. Значения вроде ТаблицаЗначений или Структура запрос не примет ни в каком виде — эти колонки перед передачей удалите.

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

Задача из загрузки Excel или CSV: есть колонки Артикул и Количество, для каждой строки нужна ссылка на номенклатуру. НайтиПоРеквизиту в цикле обращается к базе на каждой строке, а пакетный запрос делает всё за один вызов и заодно показывает не найденные и повторяющиеся артикулы.

// Общий модуль с флагом «Сервер» или модуль объекта обработки. Платформа 8.3.
// Справочник.Номенклатура с реквизитом Артикул есть в УТ 11 и БП 3.0;
// в другой конфигурации подставьте свои имена метаданных.

// Сопоставляет строки файла с номенклатурой по артикулу одним запросом.
// Параметры:
//   СтрокиФайла - ТаблицаЗначений - колонки Артикул (строка или число)
//   и Количество (число); типы колонок могут быть не заданы.
// Возвращаемое значение:
//   ТаблицаЗначений - НомерСтроки, Артикул, Количество, Номенклатура, НайденоПозиций.
Функция СопоставитьПоАртикулам(СтрокиФайла) Экспорт

	// 1. Таблица для запроса: у каждой колонки явный тип.
	ДанныеФайла = Новый ТаблицаЗначений;
	ДанныеФайла.Колонки.Добавить("НомерСтроки",
		Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(10, 0)));
	ДанныеФайла.Колонки.Добавить("Артикул",
		Новый ОписаниеТипов("Строка", , Новый КвалификаторыСтроки(50)));
	ДанныеФайла.Колонки.Добавить("Количество",
		Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(15, 3)));

	НомерСтроки = 0;
	Для Каждого СтрокаФайла Из СтрокиФайла Цикл
		НомерСтроки = НомерСтроки + 1;
		Артикул = СтрокаФайла.Артикул;
		Если ТипЗнч(Артикул) = Тип("Число") Тогда
			Артикул = Формат(Артикул, "ЧГ=0"); // без пробела между разрядами
		КонецЕсли;
		НоваяСтрока = ДанныеФайла.Добавить();
		НоваяСтрока.НомерСтроки = НомерСтроки;
		НоваяСтрока.Артикул = СокрЛП(Артикул);
		НоваяСтрока.Количество = СтрокаФайла.Количество;
	КонецЦикла;

	// 2. Пакет: таблица значений -> временная таблица -> соединение со справочником.
	Запрос = Новый Запрос;
	Запрос.Текст =
	"ВЫБРАТЬ
	|	ДанныеФайла.НомерСтроки КАК НомерСтроки,
	|	ДанныеФайла.Артикул КАК Артикул,
	|	ДанныеФайла.Количество КАК Количество
	|ПОМЕСТИТЬ ВТДанныеФайла
	|ИЗ
	|	&ДанныеФайла КАК ДанныеФайла
	|
	|ИНДЕКСИРОВАТЬ ПО
	|	Артикул
	|;
	|
	|////////////////////////////////////////////////////////////////////////////////
	|ВЫБРАТЬ
	|	ВТДанныеФайла.НомерСтроки КАК НомерСтроки,
	|	ВТДанныеФайла.Артикул КАК Артикул,
	|	ВТДанныеФайла.Количество КАК Количество,
	|	ЕСТЬNULL(МАКСИМУМ(СпрНоменклатура.Ссылка),
	|		ЗНАЧЕНИЕ(Справочник.Номенклатура.ПустаяСсылка)) КАК Номенклатура,
	|	КОЛИЧЕСТВО(РАЗЛИЧНЫЕ СпрНоменклатура.Ссылка) КАК НайденоПозиций
	|ИЗ
	|	ВТДанныеФайла КАК ВТДанныеФайла
	|		ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Номенклатура КАК СпрНоменклатура
	|		ПО ВТДанныеФайла.Артикул = СпрНоменклатура.Артикул
	|			И ВТДанныеФайла.Артикул <> """"
	|			И НЕ СпрНоменклатура.ПометкаУдаления
	|
	|СГРУППИРОВАТЬ ПО
	|	ВТДанныеФайла.НомерСтроки,
	|	ВТДанныеФайла.Артикул,
	|	ВТДанныеФайла.Количество
	|
	|УПОРЯДОЧИТЬ ПО
	|	НомерСтроки";

	Запрос.УстановитьПараметр("ДанныеФайла", ДанныеФайла);

	// 3. Результат последнего запроса пакета -> таблица значений.
	Возврат Запрос.Выполнить().Выгрузить();

КонецФункции

Разбор ключевых строк

  • Новая таблица с типами. Исходную могли собрать без типов, например при чтении табличного документа. Переливаем строки в таблицу с явными типами и обрезаем пробелы у артикула: лишний пробел по краям — частая причина «не найдено».
  • Формат(Артикул, "ЧГ=0"). Из Excel артикул иногда приходит числом. При неявном преобразовании в строку 12345 превратится в «12 345» с разделителем разрядов и ни с чем не совпадёт.
  • КвалификаторыСтроки(50). Колонка Артикул участвует в условии соединения, поэтому длина у неё ограничена.
  • ПОМЕСТИТЬ ВТДанныеФайла … ИНДЕКСИРОВАТЬ ПО Артикул. Первый запрос пакета только переносит данные во временную таблицу. Индекс по полю соединения полезен, когда строк в файле много.
  • Условие Артикул <> "" в ПО. Без него строка файла с пустым артикулом соединится со всеми позициями справочника, у которых артикул тоже не заполнен. В тексте модуля пустая строка записана четырьмя кавычками, потому что кавычки внутри строкового литерала удваиваются.
  • МАКСИМУМ и КОЛИЧЕСТВО(РАЗЛИЧНЫЕ …). Артикул в справочнике не обязан быть уникальным: без группировки дубль размножит строку файла, и количество задвоится. Группировка по номеру строки оставляет одну запись на строку файла, а НайденоПозиций показывает число кандидатов: 0 — не найдено, больше 1 — нужна ручная проверка.
  • ЕСТЬNULL. Для строки без пары левое соединение даёт NULL. Подставляем пустую ссылку, чтобы колонка Номенклатура содержала только ссылки.
  • Выполнить().Выгрузить(). У пакета Выполнить() возвращает результат последнего запроса.

Табличная часть документа в запросе

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

// Модуль объекта документа с табличной частью Товары (реквизит Номенклатура).
// Обработчик выполняется на сервере. СтрШаблон: платформа 8.3.6+
// и режим совместимости конфигурации не ниже 8.3.6.
// В более старых конфигурациях на БСП используйте
// СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку.
Процедура ОбработкаПроверкиЗаполнения(Отказ, ПроверяемыеРеквизиты)

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

	Выборка = Запрос.Выполнить().Выбрать();
	Пока Выборка.Следующий() Цикл
		Сообщение = Новый СообщениеПользователю;
		Сообщение.Текст = СтрШаблон("Строка %1: номенклатура «%2» помечена на удаление.",
			Формат(Выборка.НомерСтроки, "ЧГ=0"), Выборка.Номенклатура);
		Сообщение.Поле = "Товары[" + Формат(Выборка.НомерСтроки - 1, "ЧН=0; ЧГ=0") + "].Номенклатура";
		Сообщение.УстановитьДанные(ЭтотОбъект);
		Сообщение.Сообщить();
		Отказ = Истина;
	КонецЦикла;

КонецПроцедуры

Товары.Выгрузить(, "НомерСтроки, Номенклатура") берёт только нужные колонки — цены и суммы в СУБД гонять незачем. В Формат для индекса стоит ЧН=0: без него ноль превращается в пустую строку, и сообщение для первой строки не привяжется к полю. ЧГ=0 убирает разделитель разрядов у номеров больше 999. В конфигурациях на БСП 3.x вместо СообщениеПользователю обычно вызывают ОбщегоНазначения.СообщитьПользователю(Текст, ЭтотОбъект, Поле, , Отказ). Порядок параметров: текст, ключ данных, поле, путь к данным (здесь пропущен), Отказ — его процедура установит в Истина сама. В БСП 2.x серверного варианта нет, там вызывают ОбщегоНазначенияКлиентСервер.СообщитьПользователю с тем же порядком параметров.

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

МетодЧто возвращаетКогда использовать
Результат.Выгрузить()ТаблицаЗначенийНужен весь набор в памяти: передать дальше, загрузить в табличную часть, отдать в следующий запрос
Результат.Выгрузить(ОбходРезультатаЗапроса.ПоГруппировкам)ДеревоЗначенийЗапрос с ИТОГИ, нужна иерархия
Результат.Выбрать()ВыборкаИзРезультатаЗапросаДостаточно одного прохода по строкам, таблица в памяти не нужна
Запрос.ВыполнитьПакет()Массив результатовНужны результаты нескольких запросов пакета

Колонки выгруженной таблицы получают типы полей запроса. Если поле пришло из левого соединения без ЕСТЬNULL, в тип колонки добавится Null. Такую таблицу можно снова передать в запрос без подготовки.

Чтобы результат сразу попал в табличную часть, используйте Загрузить: Объект.Товары.Загрузить(ТаблицаРезультата). Колонки сопоставляются по именам, поэтому псевдонимы полей в запросе называйте так же, как реквизиты табличной части. Перед обходом результат удобно проверить на пустоту — варианты разобраны в статье про проверку пустого результата запроса.

Выбрать из таблицы значений запросом: когда это оправдано

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

  • соединение с таблицами базы (остатки, цены, реквизиты справочников);
  • поля ссылок через точку сразу для всех строк;
  • группировка с условием ИМЕЮЩИЕ, вычисляемые поля, ВЫБОР — то, чего нет у Свернуть.

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

Типичные ошибки

  • «Тип не может быть выбран в запросе». Колонка таблицы значений добавлена без типа, или в ней лежат значения, которые запрос не хранит: таблица значений, структура, массив. Решение — задать ОписаниеТипов при создании колонки или пересобрать таблицу функцией выше.
  • «Поле не найдено "ДанныеФайла.Артикул"». В таблице значений нет колонки с таким именем: опечатка или колонку назвали иначе при заполнении.
  • «Таблица не найдена "ВТДанныеФайла"». Временная таблица создана одним запросом, а читается другим. Внутри одного пакета менеджер не нужен. Если запросы разные, установите Запрос.МенеджерВременныхТаблиц = Новый МенеджерВременныхТаблиц и передайте этот же менеджер второму запросу.
  • «Тип не определен (ТаблицаЗначений)» или «Тип не определен (Запрос)». Код попал в клиентскую процедуру — перенесите его в &НаСервере.
  • В параметр передана коллекция формы. Объект.Товары в модуле управляемой формы — коллекция данных формы, а не таблица значений. В серверной процедуре передайте в запрос Объект.Товары.Выгрузить().
  • «Нельзя сравнивать поля неограниченной длины и поля несовместимых типов». Колонка, по которой идёт соединение, объявлена как ОписаниеТипов("Строка"). Задайте длину в квалификаторе или приведите поле в запросе: ВЫРАЗИТЬ(Т.Артикул КАК СТРОКА(50)).
  • Null в выгруженной таблице. Поле из правой части левого соединения без ЕСТЬNULL. Вызов Строка.Номенклатура.Пустая() на такой строке упадёт с ошибкой «Значение не является значением объектного типа (Пустая)». Оберните поле в ЕСТЬNULL прямо в запросе.

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

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

Массив используют как значение параметра в условиях: ГДЕ Т.Номенклатура В (&Список). Источником после ИЗ он быть не может. Если нужен именно источник, создайте таблицу значений с одной типизированной колонкой и заполните её из массива в цикле.

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

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

// Отладочная функция, выполняется на сервере.
// ДанныеФайла - ТаблицаЗначений с типизированными колонками Артикул и Количество.
Функция СодержимоеВременнойТаблицы(ДанныеФайла) Экспорт

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

	// Менеджер тот же, поэтому временная таблица ещё существует.
	Запрос.Текст = "ВЫБРАТЬ * ИЗ ВТДанныеФайла";
	Возврат Запрос.Выполнить().Выгрузить();

КонецФункции

Удобнее проверять пакеты в консоли запросов, она показывает и временные таблицы. Подробнее — в статье про консоль запросов 1С 8.3.

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

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

Нужно ли типизировать таблицу, полученную из другого запроса?

Нет. РезультатЗапроса.Выгрузить() и ТабличнаяЧасть.Выгрузить() возвращают таблицу с типами колонок. Проблемы бывают только с таблицами, собранными вручную через Колонки.Добавить без второго параметра.

Когда проще заказать

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

По теме

Не хотите разбираться сами?

Адаптируем это решение под вашу базу. Оценка бесплатно.

Оставить задачу

Станьте частью сообщества!
Войдите или зарегистрируйтесь, и вы сможете участвовать в обсуждениях.


1С, 1С:Предприятие — товарные знаки ООО «1С». Сайт не является официальным представительством фирмы «1С» и не аффилирован с ней.