При написании запросов в платформе 1С:Предприятие разработчики нередко сталкиваются с ошибкой: «Неверные параметры в операции сравнения. Нельзя сравнивать поля неограниченной длины и поля несовместимых типов». Подобное сообщение указывает на то, что СУБД не может сопоставить тип данных в поле таблицы с типом переданного в запрос параметра или выражения.
Разберем по шагам, почему возникает эта ошибка, как быстро локализовать проблему и как правильно составить программный код и текст запроса.
Проанализируем типовую ситуацию. В коде инициализируется запрос, в который передается переменная:
ЗапросПоТабелю = Новый Запрос;
ЗапросПоТабелю.Текст = "ВЫБРАТЬ
| ЛьготыСрезПоследних.Процент КАК Процент
|ИЗ
| РегистрСведений.Льготы.СрезПоследних КАК ЛьготыСрезПоследних
|ГДЕ
| ЛьготыСрезПоследних.ЛицевойСчет = &ЛицевойСчет";
ЗапросПоТабелю.УстановитьПараметр("ЛицевойСчет", ЛицевойСчет);
РезультатЗапроса = ЗапросПоТабелю.Выполнить().Выбрать();
Если в переменной ЛицевойСчет находится значение типа СправочникОбъект.ЛицевыеСчета, а измерение регистра ЛицевойСчет имеет тип СправочникСсылка.ЛицевыеСчета, возникает конфликт типов.
Объекты прикладных типов (такие как СправочникОбъект, ДокументОбъект, ПланВидовХарактеристикОбъект) существуют исключительно в оперативной памяти сервера 1С. В физических таблицах СУБД хранятся только уникальные идентификаторы (ссылки). При попытке передать объект целиком транслятор запросов 1С не может выполнить сравнение с полем базы данных и генерирует ошибку несовместимости типов.
Способ решения: перед передачей параметра в запрос необходимо явно обращаться к свойству Ссылка:
ЗапросПоТабелю.УстановитьПараметр("ЛицевойСчет", ЛицевойСчет.Ссылка);
Свойство Ссылка у ссылочных типов (СправочникСсылка, ДокументСсылка) возвращает само себя. Поэтому конструкция ЗначениеПеременной.Ссылка универсальна: она корректно отработает как в случае, если в переменной передан объект, так и в случае, если там уже хранилась ссылка.
Если в условии соединения или фильтрации участвует строковое поле неограниченной длины или поле типа ХранилищеЗначения, СУБД выдаст аналогичное предупреждение. Платформа 1С запрещает прямое сравнение, группировку и сортировку по строкам неограниченной длины.
Способ решения: ограничим длину строки с помощью функции ВЫРАЗИТЬ непосредственно в тексте запроса:
ВЫБРАТЬ
Таблица.Данные КАК Данные
ИЗ
Справочник.Контрагенты КАК Таблица
ГДЕ
ВЫРАЗИТЬ(Таблица.Комментарий КАК СТРОКА(150)) = &ПараметрКомментарий
Посмотрим на ситуацию, когда реквизит в базе данных имеет составной тип или ссылочный тип, а в параметр запроса передается Неопределено, NULL или тип, не входящий в состав разрешенных (например, число вместо ссылки). В этом случае СУБД также сообщает о невозможности сравнения несовместимых типов.
Для явного уточнения типа в запросах к полям составного типа применяются следующие конструкции:
ВЫРАЗИТЬ(Поле КАК Справочник.ИмяСправочника);ССЫЛКА: Таблица.Поле ССЫЛКА Справочник.ЛицевыеСчета;ТИПЗНАЧЕНИЯ(Поле) = ТИП(Справочник.ЛицевыеСчета).Рассмотрим еще одну критическую ошибку в исходном запросе. Наложение условия на виртуальную таблицу через секцию ГДЕ приводит к падению производительности:
// Неоптимальный вариант: фильтрация происходит после получения всех записей среза
ИЗ
РегистрСведений.Льготы.СрезПоследних КАК ЛьготыСрезПоследних
ГДЕ
ЛьготыСрезПоследних.ЛицевойСчет = &ЛицевойСчет
При таком подходе платформа сначала рассчитывает срез последних по абсолютно всей таблице регистра сведений в базе данных, и лишь затем отсекает лишние строки. Правильным решением является перенос условий во второй параметр виртуальной таблицы.
Разберем окончательный оптимизированный вариант программного кода:
ЗапросПоТабелю = Новый Запрос;
ЗапросПоТабелю.Текст = "ВЫБРАТЬ
| ЛьготыСрезПоследних.Процент КАК Процент
|ИЗ
| РегистрСведений.Льготы.СрезПоследних(&Период, ЛицевойСчет = &ЛицевойСчет) КАК ЛьготыСрезПоследних";
ЗапросПоТабелю.УстановитьПараметр("Период", ТекущаяДата());
ЗапросПоТабелю.УстановитьПараметр("ЛицевойСчет", ЛицевойСчет.Ссылка);
РезультатЗапроса = ЗапросПоТабелю.Выполнить();
Выборка = РезультатЗапроса.Выбрать();
Такой подход позволяет СУБД применить индексы на этапе формирования выборки, исключает ошибку несовместимости типов и существенно ускоряет работу программы.