Работа со строками в языке запросов 1С долгое время была ограничена лишь несколькими функциями, такими как ПОДСТРОКА и ПОДОБНО. Задача удаления лишних пробелов (аналог функции СокрЛП) часто ставила разработчиков в тупик, вынуждая либо выгружать результат запроса в таблицу значений для постобработки, либо использовать крайне громоздкие конструкции. Чтобы быстро ориентироваться во всех доступных операторах, рекомендуем использовать актуальную шпаргалку по языку запросов. Однако с развитием платформы ситуация изменилась.
В этой статье мы подробно разберем, как решить задачу удаления пробелов в запросе, начиная от современных возможностей платформы и заканчивая «хитростями», которые пригодятся на старых версиях системы. Для нормализации данных в базе есть обработка очистки наименований и артикулов от пробелов.
Начиная с релиза 8.3.20.1549, фирма «1С» значительно расширила возможности языка запросов. Теперь нам не нужно изобретать сложные алгоритмы, так как в язык добавлены нативные функции для работы со строками. Проанализируем основные функции, которые решают нашу задачу:
СОКРЛ(Строка) — удаляет незначащие пробелы слева.СОКРП(Строка) — удаляет незначащие пробелы справа.СОКРЛП(Строка) — удаляет пробелы с обеих сторон (самый частый сценарий).СТРЗАМЕНИТЬ(Строка, ПодстрокаПоиска, ПодстрокаЗамены) — позволяет удалить вообще все пробелы внутри строки, заменив их на пустую строку.Рассмотрим пример использования этих функций в реальном запросе:
ВЫБРАТЬ
СОКРЛП(Должности.Наименование) КАК НаименованиеБезПробелов,
СТРЗАМЕНИТЬ(Должности.Наименование, " ", "") КАК ПолнаяОчисткаОтПробелов
ИЗ
Справочник.Должности КАК Должности
Важное замечание: Эти функции транслируются непосредственно в SQL-запросы (например, в LTRIM(RTRIM(...)) для MS SQL Server). Это обеспечивает высокую скорость выполнения, однако стоит помнить, что использование таких функций в секции ГДЕ может привести к невозможности использования индексов по данному полю. Для отладки сложных выборок и анализа производительности отлично подойдет функциональная консоль запросов с поддержкой временных таблиц — есть функциональная консоль запросов и СКД для 1С.
Если ваша задача — вывести очищенные данные в отчет, и вы используете платформу ниже 8.3.20, самым правильным и простым решением будет использование вычисляемых полей СКД. Выясним, почему это удобно:
В языке выражений СКД функции СокрЛП, Лев, Прав и другие были доступны гораздо раньше, чем в языке запросов. Разберем по шагам, как это настроить:
НаименованиеОчищенное).СокрЛП(Наименование).Преимущество этого метода в том, что расчет происходит на сервере приложений 1С уже после получения данных из базы.
Иногда возникают ситуации, когда использовать СКД невозможно, а платформа не поддерживает новые функции. В таких случаях программисты прибегают к «высшему пилотажу» — разбору строки на символы прямо в запросе. Рассмотрим логику этого метода:
Для реализации очистки нам нужно создать последовательность чисел (разрядов), с помощью которых мы будем «разрезать» строку функцией ПОДСТРОКА. Проанализируем пример кода, который формирует таблицу символов, отсекая пустые значения:
// Создаем вспомогательную таблицу чисел
ВЫБРАТЬ 0 КАК сч ПОМЕСТИТЬ т01 ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 1;
////////////////////////////////////////////////////////////////
ВЫБРАТЬ т01.сч * 2 + т02.сч КАК сч ПОМЕСТИТЬ т04 ИЗ т01 КАК т01, т01 КАК т02;
////////////////////////////////////////////////////////////////
ВЫБРАТЬ т01.сч * 4 + т02.сч КАК сч ПОМЕСТИТЬ т16 ИЗ т04 КАК т01, т04 КАК т02;
////////////////////////////////////////////////////////////////
// Разбираем строку на символы
ВЫБРАТЬ
Должности.Ссылка КАК Ссылка,
ПОДСТРОКА(Должности.Наименование, разряды.сч, 1) КАК Символ,
разряды.сч КАК Позиция
ПОМЕСТИТЬ тВсеСимволы
ИЗ
Справочник.Должности КАК Должности,
т16 КАК разряды
ГДЕ
разряды.сч > 0
И ПОДСТРОКА(Должности.Наименование, разряды.сч, 1) <> ""
И ПОДСТРОКА(Должности.Наименование, разряды.сч, 1) <> " ";
После такого разбора данные можно анализировать более глубоко. Например, если вам требуется не просто удалить пробелы, а реализовать подсчет количества слов в тексте или выполнить интеллектуальное сравнение строк (поможет инструмент поиска и устранения некорректных записей) с использованием алгоритма Левенштейна, лучше воспользоваться готовыми алгоритмами обработки строковых данных.
Существует распространенное заблуждение, что функция ВЫРАЗИТЬ(Поле КАК СТРОКА(N)) работает как СокрЛП. Разберем, как это работает на самом деле.
Когда мы приводим строку неограниченной длины к строке фиксированной длины, 1С действительно отсекает лишние данные. Однако, если исходная строка короче, чем указанная длина N, СУБД (особенно Microsoft SQL Server) может, напротив, дополнить строку пробелами справа. Поэтому использовать ВЫРАЗИТЬ для «очистки» можно только в связке с проверками на пустые значения, как показано ниже:
ВЫБОР
КОГДА ВЫРАЗИТЬ(Наименование КАК СТРОКА(100)) = ""
ТОГДА ""
ИНАЧЕ Наименование
КОНЕЦ
Часто разработчики сталкиваются с тем, что даже СОКРЛП в запросе не помогает. Причина кроется в так называемых «неразрывных пробелах» (символ с кодом 160). В 1С они часто попадают при копировании данных из Excel или веб-браузеров. Стандартные строковые функции SQL могут не воспринимать их как пробелы.
Для борьбы с ними на современных платформах лучше всего комбинировать функции. К сожалению, функцию СИМВОЛ() в запросе использовать нельзя, поэтому символ неразрывного пробела обычно передают как параметр запроса:
// В коде 1С:
Запрос.УстановитьПараметр("НеразрывныйПробел", Символы.НПП);
// В тексте запроса:
ВЫБРАТЬ
СОКРЛП(СТРЗАМЕНИТЬ(Должности.Наименование, &НеразрывныйПробел, " ")) КАК ЧистоеНаименование
ИЗ
Справочник.Должности КАК Должности
В заключение проанализируем ситуацию с точки зрения производительности. Выполнение любых манипуляций со строками в запросе — это нагрузка на сервер базы данных. Хорошим тоном считается очистка данных при записи объекта — для этого подойдёт модуль автоматической проверки данных перед записью.
Если вы добавите в модуль справочника Должности следующий код, вам вообще не придется задумываться об удалении пробелов в запросах:
Процедура ПередЗаписью(Отказ)
Наименование = СокрЛП(Наименование);
КонецПроцедуры
Если же ваша база уже содержит много некорректных данных, вам поможет универсальная обработка для очистки базы, которая позволяет массово редактировать и удалять объекты по заданным фильтрам — для решения этой задачи подойдёт универсальная обработка очистки и редактирования данных. Этот простой шаг гарантирует чистоту данных в базе и максимально быстрые запросы, так как они будут работать с уже подготовленными строками.