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

Программист 1С v8.3 (Обычные формы) 1С:Управление торговлей Управленческий учет Торговля и дистрибуция
← На главную

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

Причина возникновения ошибки типизации

Когда мы передаем ТаблицаЗначений в запрос в качестве параметра, система 1С пытается создать на стороне СУБД (SQL Server, PostgreSQL и др.) реальную временную таблицу. Для этого СУБД должна четко «понимать», какие типы данных будут храниться в колонках, какова их длина и точность. Если колонка в ТЗ создана динамически (например, выгрузкой из построителя отчета или просто методом Колонки.Добавить("Имя") без указания типов), ее тип считается неопределенным или слишком широким.

Проанализируем ситуацию: если мы пытаемся использовать операторы ССЫЛКА или ВЫРАЗИТЬ к такой колонке внутри запроса, платформа выдает ошибку, так как не может сопоставить «нетипизированное» поле временной таблицы с объектами метаданных базы данных.

Решение №1: Явная типизация колонок Таблицы Значений

Самый надежный способ — это объявить структуру Таблицы Значений заранее, четко указав ОписаниеТипов для каждой колонки. Выясним, как это реализовать на практике. Разберем пример, где в колонке Информация могут храниться ссылки на контрагентов, строки или числа.


// 1. Создаем массив типов, которые могут встретиться в колонке
МассивТипов = Новый Массив;
МассивТипов.Добавить(Тип("СправочникСсылка.Контрагенты"));
МассивТипов.Добавить(Тип("Строка"));
МассивТипов.Добавить(Тип("Число"));

// 2. Создаем объект ОписаниеТипов на основании массива
ОписаниеТиповДанных = Новый ОписаниеТипов(МассивТипов);

// 3. Создаем таблицу и добавляем колонку с указанным типом
ТЗ = Новый ТаблицаЗначений;
ТЗ.Колонки.Добавить("Информация", ОписаниеТиповДанных);

// 4. Заполняем таблицу данными
НоваяСтрока = ТЗ.Добавить();
НоваяСтрока.Информация = Справочники.Контрагенты.НайтиПоКоду("00001");

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

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

Важный нюанс: использование ОписаниеТипов позволяет платформе 1С правильно создать структуру временной таблицы на SQL-сервере, что делает доступными операторы сравнения типов.

Решение №2: Изменение логики поиска (Оптимальный подход)

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

Проанализируем алгоритм:

  1. Ищем все ссылки контрагентов, чье наименование удовлетворяет условию ПОДОБНО.
  2. Помещаем эти ссылки во временную таблицу.
  3. Выбираем документы из базы, фильтруя их по этой временной таблице.

Запрос = Новый Запрос;
Запрос.УстановитьПараметр("СтрокаПоиска", "%" + ТекстПоиска + "%");

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

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

Особенности работы с графами журналов

В старых конфигурациях (например, УТ 10.3) часто используются Графы журналов. Нужно учитывать, что «Графа» — это виртуальное поле. При попытке выгрузить данные из табличного поля формы (через ЭлементыФормы.Список.Значение), в колонку Информация может попасть не ссылка на объект, а его строковое представление (текст, который видит пользователь).

Если в ТЗ вместо ссылок попали строки, оператор ССЫЛКА Справочник.Контрагенты всегда будет выдавать ошибку или ложь. В таких случаях необходимо:

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

← На главную