В практике разработки на платформе 1С:Предприятие часто возникает задача: передать имеющуюся в памяти Таблицу Значений (ТЗ) в запрос для дальнейшей обработки, фильтрации или соединения с данными информационной базы. Однако при работе с колонками, содержащими составные типы данных (например, когда в одной колонке могут быть ссылки на разные справочники или документы), разработчики сталкиваются с ошибками вида Несовместимые типы или Тип не может быть выбран в запросе. Рассмотрим, почему это происходит и как правильно решить эту задачу.
Когда мы передаем ТаблицаЗначений в запрос в качестве параметра, система 1С пытается создать на стороне СУБД (SQL Server, PostgreSQL и др.) реальную временную таблицу. Для этого СУБД должна четко «понимать», какие типы данных будут храниться в колонках, какова их длина и точность. Если колонка в ТЗ создана динамически (например, выгрузкой из построителя отчета или просто методом Колонки.Добавить("Имя") без указания типов), ее тип считается неопределенным или слишком широким.
Проанализируем ситуацию: если мы пытаемся использовать операторы ССЫЛКА или ВЫРАЗИТЬ к такой колонке внутри запроса, платформа выдает ошибку, так как не может сопоставить «нетипизированное» поле временной таблицы с объектами метаданных базы данных.
Самый надежный способ — это объявить структуру Таблицы Значений заранее, четко указав ОписаниеТипов для каждой колонки. Выясним, как это реализовать на практике. Разберем пример, где в колонке Информация могут храниться ссылки на контрагентов, строки или числа.
// 1. Создаем массив типов, которые могут встретиться в колонке
МассивТипов = Новый Массив;
МассивТипов.Добавить(Тип("СправочникСсылка.Контрагенты"));
МассивТипов.Добавить(Тип("Строка"));
МассивТипов.Добавить(Тип("Число"));
// 2. Создаем объект ОписаниеТипов на основании массива
ОписаниеТиповДанных = Новый ОписаниеТипов(МассивТипов);
// 3. Создаем таблицу и добавляем колонку с указанным типом
ТЗ = Новый ТаблицаЗначений;
ТЗ.Колонки.Добавить("Информация", ОписаниеТиповДанных);
// 4. Заполняем таблицу данными
НоваяСтрока = ТЗ.Добавить();
НоваяСтрока.Информация = Справочники.Контрагенты.НайтиПоКоду("00001");
// 5. Теперь ТЗ можно передавать в запрос без ошибок
Запрос = Новый Запрос;
Запрос.УстановитьПараметр("ТЗ", ТЗ);
Запрос.Текст =
"ВЫБРАТЬ
| ТЗ.Информация КАК Контрагент
|ПОМЕСТИТЬ ВТДанные
|ИЗ
| &ТЗ КАК ТЗ
|;
|
|ВЫБРАТЬ
| ВТДанные.Контрагент
|ИЗ
| ВТДанные КАК ВТДанные
|ГДЕ
| ВТДанные.Контрагент ССЫЛКА Справочник.Контрагенты";
Результат = Запрос.Выполнить();
Важный нюанс: использование ОписаниеТипов позволяет платформе 1С правильно создать структуру временной таблицы на SQL-сервере, что делает доступными операторы сравнения типов.
Иногда задача поиска по части наименования контрагента в журнале документов решается неэффективно через выгрузку в ТЗ. Рассмотрим более производительный вариант. Вместо того чтобы выгружать все строки журнала в память, а потом пытаться «пропихнуть» их обратно в запрос, лучше сначала найти подходящих контрагентов в базе данных, а затем соединить их с документами.
Проанализируем алгоритм:
ПОДОБНО.
Запрос = Новый Запрос;
Запрос.УстановитьПараметр("СтрокаПоиска", "%" + ТекстПоиска + "%");
Запрос.Текст =
"ВЫБРАТЬ
| Контрагенты.Ссылка КАК Ссылка
|ПОМЕСТИТЬ ВТ_НужныеКонтрагенты
|ИЗ
| Справочник.Контрагенты КАК Контрагенты
|ГДЕ
| Контрагенты.Наименование ПОДОБНО &СтрокаПоиска
|;
|
|////////////////////////////////////////////////////////////////////////////////
|ВЫБРАТЬ
| Заказы.Ссылка КАК ДокументСсылка,
| Заказы.Контрагент КАК Контрагент
|ИЗ
| Документ.ЗаказПокупателя КАК Заказы
|ГДЕ
| Заказы.Контрагент В (ВЫБРАТЬ Ссылка ИЗ ВТ_НужныеКонтрагенты)";
Выборка = Запрос.Выполнить().Выбрать();
В старых конфигурациях (например, УТ 10.3) часто используются Графы журналов. Нужно учитывать, что «Графа» — это виртуальное поле. При попытке выгрузить данные из табличного поля формы (через ЭлементыФормы.Список.Значение), в колонку Информация может попасть не ссылка на объект, а его строковое представление (текст, который видит пользователь).
Если в ТЗ вместо ссылок попали строки, оператор ССЫЛКА Справочник.Контрагенты всегда будет выдавать ошибку или ложь. В таких случаях необходимо:
Строка и искать соответствие по коду или наименованию, что менее надежно.Резюме: для успешного обращения к составным типам в запросах через ТЗ всегда используйте ОписаниеТипов при создании таблицы. Если же данных много, старайтесь перенести логику поиска целиком на сторону сервера приложений и СУБД, избегая лишних итераций с выгрузкой данных в промежуточные таблицы значений.