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