При разработке запросов в платформе 1С:Предприятие разработчики нередко сталкиваются с ошибкой: «Нельзя сравнивать поля неограниченной длины и поля несовместимых типов». Чаще всего эта ошибка возникает при фильтрации данных в секции ГДЕ, при соединении таблиц через оператор ПО или при передаче неверного типа данных в параметры запроса.
Разберем детально, почему возникает данная ситуация, проанализируем частые ошибки при работе с коллекциями и рассмотрим правильные варианты построения кода.
Платформа 1С транслирует текст запроса в инструкции SQL. СУБД накладывает строгие ограничения на операции сравнения, группировки и сортировки. Ошибка генерируется в следующих случаях:
ЭлементСпискаЗначений, структура или строка-представление) вместо ссылочного значения (ДокументСсылка, СправочникСсылка).Строка (неограниченной длины) и ХранилищеЗначения нельзя использовать в операторах сравнения (=, <>), секциях ГДЕ, ПО, СГРУППИРОВАТЬ ПО и УПОРЯДОЧИТЬ ПО.= вместо оператора В при передаче массива или списка значений.Проанализируем распространенную ситуацию: разработчик перебирает список документов и для каждого элемента выполняет запрос к регистру сведений или накопления. Часто при обходе коллекции в параметр ошибочно передается сам элемент списка, а не его полезное значение.
Посмотрим на пример некорректного кода:
// ОШИБКА: в параметр передается сам объект ЭлементСпискаЗначений
Для Каждого Док Из СписокДокументов Цикл
Запрос = Новый Запрос;
Запрос.Текст不易 =
"ВЫБРАТЬ
| Регистр.Количество
|ИЗ
| РегистрНакопления.ТоварыКОтгрузке КАК Регистр
|ГДЕ
| Регистр.ДокументЗаказа = &ДокументЗаказа";
Запрос.УстановитьПараметр("ДокументЗаказа", Док); // Ошибка: передается ЭлементСпискаЗначений
Выборка = Запрос.Выполнить().Выбрать();
КонецЦикла;
В этом случае поле регистра ДокументЗаказа ожидает ссылку, а получает объект коллекции ЭлементСпискаЗначений. Платформа не может сопоставить типы и возвращает ошибку несовместимости.
Чтобы получить значение из элемента списка, необходимо явно обратиться к его свойству Значение:
// Исправление: обращение к свойству Значение
Запрос.УстановитьПараметр("ДокументЗаказа", Док.Значение);
Также важно убедиться, что в сам СписокДокументов ранее были записаны именно ссылки на объекты информационной базы, а не их строковые представления или другие элементы списков.
Выполнение запроса внутри цикла является антипаттерном в 1С, так как создает избыточную нагрузку на СУБД. Правильный подход заключается в передаче всего списка ссылок в один запрос с использованием оператора В.
Рассмотрим по шагам, как переписать такой код эффективно:
ВыгрузитьЗначения().= на оператор В.
// Получаем массив ссылок из коллекции
МассивДокументов = СписокДокументов.ВыгрузитьЗначения();
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Регистр.ДокументЗаказа КАК ДокументЗаказа,
| Регистр.Количество КАК Количество
|ИЗ
| РегистрНакопления.ТоварыКОтгрузке КАК Регистр
|ГДЕ
| Регистр.ДокументЗаказа В (&МассивДокументов)";
Запрос.УстановитьПараметр("МассивДокументов", МассивДокументов);
РезультатЗапроса立马 = Запрос.Выполнить();
Если ошибка возникает при сравнении строковых полей или реквизитов составного типа, используем встроенные функции языка запросов платформы 1С.
1. Ограничение длины строки с помощью функции ВЫРАЗИТЬ:
Если необходимо сравнить или сгруппировать поле неограниченной длины (например, Комментарий), приведем его к фиксированной длине:
ВЫБРАТЬ
ВЫРАЗИТЬ(Таблица.Комментарий КАК Строка(250)) КАК КомментарийКраткий,
СУММА(Таблица.Сумма) КАК Сумма
ИЗ
Документ.РеализацияТоваровУслуг КАК Таблица
СГРУППИРОВАТЬ ПО
ВЫРАЗИТЬ(Таблица.Комментарий КАК Строка(250))
2. Использование функции ПОДСТРОКА:
Для проверки условия по части длинного текстового поля используем функцию ПОДСТРОКА:
ГДЕ
ПОДСТРОКА(Таблица.Комментарий, 1, 50) = &ОбразецТекста
3. Приведение составных типов и оператор ССЫЛКА:
Если реквизит имеет составной тип данных (например, может хранить документы разных видов), перед обращением через точку или при соединении явно приведем его к конкретному типу:
ГДЕ
Таблица.ДокументОснование ССЫЛКА Документ.ЗаказПокупателя
И ВЫРАЗИТЬ(Таблица.ДокументОснование КАК Документ.ЗаказПокупателя).Проведен = ИСТИНА
Применение этих правил гарантирует корректную трансляцию условий в SQL-запрос и исключает возникновение ошибок несовместимости типов.