Как правильно объединять строки в запросе 1С и избежать ошибки несовместимости типов?

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

При написании запросов в платформе 1С:Предприятие разработчики часто сталкиваются с необходимостью объединить строковое поле таблицы со строковым литералом или другим полем. Однако простая операция сложения через знак плюс + может приводить к ошибке несовместимости типов. Разберем по шагам, почему возникает эта ошибка и как правильно реализовать конкатенацию строк в запросе.

Причины возникновения ошибки несовместимости типов при сложении строк

Выясним причину, по которой платформа выдает ошибку при выполнении запроса:

  1. Строки неограниченной длины: в языке запросов 1С бинарный оператор сложения + допустимо использовать только со строками ограниченной длины. Если поле таблицы базы данных имеет неограниченную длину (например, реквизит с типом Строка без указания длины), СУБД не может выполнить прямое сложение.
  2. Использование системных представлений: функция ПРЕДСТАВЛЕНИЕ() возвращает специальный системный тип, а не примитивную строку, поэтому ее результат нельзя соединять со строковыми литералами через оператор +.
  3. Попадание значений NULL: при выполнении левых соединений строковое поле может содержать значение NULL, что при конкатенации также приводит к ошибкам.
  4. Неправильная передача параметров: частая ошибка в коде на встроенном языке — передача переменной ЭтотОбъект вместо ссылки на элемент ЭтотОбъект.Ссылка в качестве параметра запроса.

Способ 1. Приведение строки к ограниченной длине с помощью ВЫРАЗИТЬ

Рассмотрим основной способ решения проблемы для строк неограниченной длины. Чтобы выполнить конкатенацию, необходимо явно ограничить длину исходного поля оператором ВЫРАЗИТЬ.

Посмотрим на пример запроса:


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |    ВЫРАЗИТЬ(Номенклатура.Наименование КАК СТРОКА(150)) + "" тест"" КАК Номенклатура
    |ИЗ
    |    Справочник.Номенклатура КАК Номенклатура
    |ГДЕ
    |    Номенклатура.Ссылка = &Ссылка";

Запрос.УстановитьПараметр("Ссылка", ЭтотОбъект.Ссылка);
Результат = Запрос.Выполнить().Выгрузить();

Важно: оператор ВЫРАЗИТЬ(Поле КАК СТРОКА(N)) имеет платформенное ограничение: длина N не может превышать 1024 символа. Если длина исходных данных больше этого значения, строка будет обрезана.

Способ 2. Использование функции ПОДСТРОКА

Проанализируем альтернативный вариант приведения типа. Вместо ВЫРАЗИТЬ можно использовать встроенную функцию ПОДСТРОКА(), которая возвращает строку гарантированно ограниченной длины:


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |    ПОДСТРОКА(Номенклатура.Наименование, 1, 150) + "" тест"" КАК Номенклатура
    |ИЗ
    |    Справочник.Номенклатура КАК Номенклатура
    |ГДЕ
    |    Номенклатура.Ссылка = &Ссылка";

Запрос.УстановитьПараметр("Ссылка", ЭтотОбъект.Ссылка);
Результат = Запрос.Выполнить().Выгрузить();

Способ 3. Очистка незначащих пробелов функциями СОКРП и СОКРЛП

Разберем ситуацию, когда реквизит имеет фиксированную длину. СУБД автоматически дополняет строку пробелами справа до максимального размера. Если сложить такое поле со строкой + " тест", добавленный текст окажется далеко в конце после всех незначащих пробелов.

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


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |    СОКРП(Номенклатура.Наименование) + "" тест"" КАК Номенклатура
    |ИЗ
    |    Справочник.Номенклатура КАК Номенклатура
    |ГДЕ
    |    Номенклатура.Ссылка = &Ссылка";

Запрос.УстановитьПараметр("Ссылка", ЭтотОбъект.Ссылка);
Результат = Запрос.Выполнить().Выгрузить();

Если поле является строкой неограниченной длины и одновременно содержит хвостовые пробелы, функции можно скомбинировать: СОКРП(ВЫРАЗИТЬ(Номенклатура.Наименование КАК СТРОКА(150))) + " тест".

Способ 4. Защита от значений NULL

Если реквизит получается из левого соединения и может содержать значение NULL, обязательно используем функцию ЕСТЬNULL():


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |    ЕСТЬNULL(СОКРП(Номенклатура.Наименование), """") + "" тест"" КАК Номенклатура
    |ИЗ
    |    Справочник.Номенклатура КАК Номенклатура
    |ГДЕ
    |    Номенклатура.Ссылка = &Ссылка";

Запрос.УстановитьПараметр("Ссылка", ЭтотОбъект.Ссылка);
Результат = Запрос.Выполнить().Выгрузить();

Способ 5. Постобработка на встроенном языке

Когда требуется сложная конкатенация большого количества полей или работа со строками длиной более 1024 символов, оптимальным решением является перенос объединения на уровень встроенного языка 1С. В запросе выбираются исходные поля, а склейка выполняется через функцию СтрШаблон() или оператор + в цикле обхода выборки.

Посмотрим на пример постобработки:


Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
    ПолноеНаименование = СтрШаблон("%1 тест", СокрЛП(Выборка.Наименование));
КонецЦикла;
← На главную