При разработке запросов в платформе 1С:Предприятие разработчики часто сталкиваются с ошибкой: «Неверные параметры в операции сравнения. Нельзя сравнивать поля неограниченной длины и поля несовместимых типов». Чаще всего эта ситуация возникает при попытке наложить отбор на строковый реквизит без ограничения длины (например, текст сертификата ЭЦП, комментарий, лог или XML-данные).
Разберем подробнее, почему возникает данная ошибка, и рассмотрим практические способы ее устранения — от быстрых доработок запроса до архитектурно правильного проектирования структуры данных.
Выясним причину такого поведения платформы и СУБД. Поля с типом Строка неограниченной длины хранятся в реляционных базах данных как большие текстовые объекты (типы CLOB, TEXT или VARCHAR(MAX)). Для таких полей действуют строгие технические ограничения:
=, <>, В), сортировки (УПОРЯДОЧИТЬ ПО), группировки (СГРУППИРОВАТЬ ПО) и устранения дублей (РАЗЛИЧНЫЕ).Если необходимо выполнить отбор или проверку по фрагменту длинной строки непосредственно в тексте запроса, поле неограниченной длины можно привести к строке фиксированной длины с помощью встроенной функции ПОДСТРОКА.
Посмотрим на пример правильного формирования условия в запросе:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ЭЦП.Ссылка КАК Ссылка,
| ЭЦП.Наименование КАК Наименование
|ИЗ
| Справочник.ЭЦП КАК ЭЦП
|ГДЕ
| ПОДСТРОКА(ЭЦП.Сертификат, 1, 1000) = ПОДСТРОКА(&Сертификат, 1, 1000)";
Запрос.УстановитьПараметр("Сертификат", ИскомыйСертификатСтрока);
Результат = Запрос.Выполнить();
Важные нюансы использования функции ПОДСТРОКА:
ПОДСТРОКА(Поле, Начало, Длина) преобразует неограниченное поле в строку фиксированной длины. Не рекомендуется задавать параметр длины более 1024 символов при операциях соединения и индексирования временных таблиц.ГДЕ отключает использование индексов СУБД и приводит к полному сканированию таблицы (Full Table Scan). На больших объемах данных такой запрос будет выполняться медленно.Для таких сущностей, как сертификаты электронной подписи, ключевые данные или произвольные длинные тексты, правильным стандартом разработки является хранение контрольной суммы (хэша) или отпечатка в отдельном реквизите.
Разберем по шагам, как это реализовать:
ЭЦП) создадим реквизит Отпечаток с типом Строка(40) или Строка(64).Отпечаток установим свойство Индексировать (или «Индексировать с доп. упорядочиванием»).ХешированиеДанных.Посмотрим на пример вычисления хэш-суммы перед записью объекта:
Хеширование = Новый ХешированиеДанных(ХешФункция.SHA1);
Хеширование.Добавить(Объект.Сертификат);
Объект.Отпечаток = Хеширование.ХешСумма;
После этого поиск и сравнение в запросах выполняются по компактному индексированному полю, что обеспечивает максимальное быстродействие:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ЭЦП.Ссылка КАК Ссылка
|ИЗ
| Справочник.ЭЦП КАК ЭЦП
|ГДЕ
| ЭЦП.Отпечаток = &Отпечаток";
Запрос.УстановитьПараметр("Отпечаток", ИскомыйОтпечаток);
Выборка = Запрос.Выполнить().Выбрать();
Если объем данных в выборке невелик и структуру метаданных менять нельзя, проанализируем вариант с получением данных без условий на неограниченное поле и последующим сравнением на встроенном языке 1С.
Рассмотрим пример реализации:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ЭЦП.Ссылка КАК Ссылка,
| ЭЦП.Сертификат КАК Сертификат
|ИЗ
| Справочник.ЭЦП КАК ЭЦП
|ГДЕ
| НЕ ЭЦП.ПометкаУдаления";
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
// Сравнение строк целиком методами встроенного языка
Если СтрСравнить(Выборка.Сертификат, ИскомыйСертификат) = 0 Тогда
// Найдено точное совпадение
СсылкаНаСертификат = Выборка.Ссылка;
Прервать;
КонецЕсли;
КонецЦикла;
Обратите внимание: этот вариант допустим только тогда, когда количество строк в таблице гарантированно ограничено другими условиями (например, отбором по владельцу или организации), иначе выборка большого объема тяжелых строк приведет к перерасходу оперативной памяти сервера.
Если поле неограниченной длины содержит текстовые описания, статьи или комментарии, и вам необходимо выполнять контекстный поиск фрагментов или слов, оптимально использовать встроенный механизм платформы — ПолнотекстовыйПоиск. Этот механизм не накладывает ограничений на длину текста и обеспечивает быстрый поиск без блокировки ресурсов базы данных.