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