Как использовать тип УникальныйИдентификатор в запросе 1С и избежать ошибки «Тип не может быть выбран в запросе»

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

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

В этой статье мы подробно разберем, почему возникает эта проблема, как она связана с версиями платформы «1С:Предприятие» и какие существуют способы её обхода, если обновить платформу прямо сейчас невозможно.

Разбор ситуации: почему возникает ошибка

Давайте проанализируем ситуацию, с которой столкнулся автор темы. Имеется регистр сведений, где одним из измерений является УникальныйИдентификатор. Проблем с выборкой данных из самого регистра нет. Однако, как только мы пытаемся передать таблицу значений, содержащую колонку с этим типом, во временную таблицу (ВТ) запроса, система выдает отказ.

Рассмотрим пример проблемного кода:


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

Запрос.УстановитьПараметр("СписокСообщений", СписокСообщений);
Результат = Запрос.Выполнить(); // Именно здесь происходит падение с ошибкой

Причина кроется в том, как платформа 1С транслирует объекты из оперативной памяти (Таблица Значений) в физические таблицы СУБД (SQL Server, PostgreSQL и др.). До определенных релизов механизм создания временных таблиц просто «не умел» сопоставлять внутренний тип 1С УникальныйИдентификатор с соответствующими типами в базе данных при передаче ТЗ в качестве параметра.

Решение №1: Обновление платформы (Рекомендуемое)

Самый правильный и современный способ решить проблему — убедиться, что вы используете актуальную версию платформы. Ограничение на использование типа УникальныйИдентификатор в колонках таблиц значений для запросов было официально снято.

Проанализируем хронологию исправлений:

  1. До версии 8.3.12: Ошибка стабильно воспроизводилась при любых попытках поместить ТЗ с GUID во временную таблицу.
  2. Версия 8.3.13: Начиная с этого релиза (а именно с 8.3.13.1513), работа с типом УникальныйИдентификатор в запросах стала полноценной. Платформа научилась корректно типизировать такие колонки во временных таблицах.

Если ваша конфигурация работает на платформе версии 8.3.13 и выше, вам достаточно просто убедиться, что колонка в Таблице Значений типизирована. Если ТЗ создается динамически, обязательно указывайте тип при добавлении колонки:


МассивТипов = Новый Массив;
МассивТипов.Добавить(Тип("УникальныйИдентификатор"));
ОписаниеТипаУИД = Новый ОписаниеТипов(МассивТипов);

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

Решение №2: Преобразование в строковый тип (Workaround)

Если по каким-то причинам проект жестко привязан к старой версии платформы (например, 8.3.10), то единственным надежным способом остается использование строкового представления идентификатора. Рассмотрим, как это реализовать эффективно.

Проанализируем шаги преобразования:

  1. В исходной Таблице Значений создаем дополнительную колонку с типом Строка(36).
  2. Перебираем таблицу и заполняем новую колонку значением Строка(УИД).
  3. В запросе обращаемся уже к строковой колонке.

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

Для Каждого Стр Из ТЗ Цикл
    Стр.ИдентификаторСтрокой = Строка(Стр.ИдентификаторСообщения);
КонецЦикла;

// В запросе используем ИдентификаторСтрокой вместо ИдентификаторСообщения

Важное замечание по производительности: Как отмечали участники обсуждения, использование строк вместо «родного» типа UUID может замедлить работу запроса на больших объемах данных. Это связано с тем, что индекс по строке (36 символов в кодировке UTF-16 занимает 72 байта) работает медленнее и занимает больше места, чем индекс по 16-байтовому бинарному представлению УникальныйИдентификатор. Если в вашей таблице миллионы записей, старайтесь всё же обновить платформу.

Решение №3: Разница между Массивом и Таблицей Значений

Выясним одну важную деталь, которая часто вводит в заблуждение начинающих разработчиков. Обратите внимание на разницу в поведении параметров:

Использование в условии ГДЕ ... В (&Массив)
Если вы просто передаете список идентификаторов в массив и используете его в условии запроса, это будет работать даже на старых версиях платформ.


МассивУИД = Новый Массив;
МассивУИД.Добавить(Новый УникальныйИдентификатор("..."));

Запрос = Новый Запрос("ВЫБРАТЬ * ИЗ РегистрСведений.Данные ГДЕ Идентификатор В (&МассивУИД)");
Запрос.УстановитьПараметр("МассивУИД", МассивУИД);
// Это сработает везде!

Помещение во Временную Таблицу
Ошибка возникает только тогда, когда идентификатор является частью структуры таблицы, которую вы пытаетесь «закачать» в SQL через ПОМЕСТИТЬ. Если вам нужно просто отфильтровать данные, используйте массив. Если же вам нужно соединить (JOIN) вашу таблицу с данными БД по этому полю — придется использовать способы, описанные выше.

Производительность и хранение в СУБД

Давайте разберем, почему программисты так борются за тип УникальныйИдентификатор. В базе данных SQL Server этот тип хранится как uniqueidentifier (16 байт). В PostgreSQL это тип uuid.

Сравним с хранением строки:

Поэтому, если ваша задача подразумевает высоконагруженную работу с измерениями регистров, всегда отдавайте предпочтение оригинальному типу УникальныйИдентификатор, даже если это требует обновления версии платформы на сервере.

Подведем итоги

Мы выяснили, что ошибка «Тип не может быть выбран в запросе» при работе с GUID — это историческое ограничение платформы «1С:Предприятие 8.3», которое было успешно устранено в ветке 8.3.13.

Для решения проблемы рекомендуем придерживаться следующего алгоритма:

  1. Проверьте версию платформы. Если она ниже 8.3.13.1513 — запланируйте обновление.
  2. Если обновление невозможно — используйте временную колонку с типом Строка(36), заполняя её через Строка(УИД) перед передачей в запрос.
  3. Если вам нужно только условие фильтрации (без соединений), используйте тип Массив с элементами УникальныйИдентификатор — это работает на всех релизах.
  4. Всегда типизируйте колонки в Таблицах Значений перед их использованием в запросах, чтобы избежать неопределенности типов.

Рассмотренные подходы позволят вам эффективно работать с уникальными идентификаторами, сохраняя производительность системы и чистоту кода.

← На главную