Строка в запросе 1С долго была слабым местом: до версии 8.3.20 язык запросов из строковых операций умел только склеивать строки через +, вырезать кусок функцией ПОДСТРОКА() и сравнивать с шаблоном через ПОДОБНО. Остальное делали в коде. В 8.3.20 появился полноценный набор строковых функций. Ниже — что доступно в каждой версии, примеры поиска, склейки и очистки данных, ограничения строк неограниченной длины. Общий синтаксис разобран в статье о языке запросов 1С, здесь — только строки.
Шпаргалка по строковым функциям в запросе 1С. Первые три строки таблицы работают на любой версии 8.3, остальные функции, по данным блога разработчиков «1С:Зазеркалье», появились в 8.3.20.1549.
| Функция | Что делает | Пример | Версия |
|---|---|---|---|
+ | соединяет строки | Наименование + " / " + Артикул | любая 8.3 |
ПОДСТРОКА(Стр, Начало, Длина) | вырезает часть строки | ПОДСТРОКА(Номер, 1, 4) | любая 8.3 |
ПОДОБНО | сравнивает с шаблоном | Наименование ПОДОБНО "%кабель%" | любая 8.3 |
ДЛИНАСТРОКИ(Стр) | длина строки | ДЛИНАСТРОКИ(ИНН) = 12 | 8.3.20 |
СОКРЛ, СОКРП, СОКРЛП | убирают пробелы слева, справа, с обеих сторон | СОКРЛП(Артикул) | 8.3.20 |
ЛЕВ(Стр, N), ПРАВ(Стр, N) | первые или последние N символов | ЛЕВ(Номер, 4) | 8.3.20 |
СТРНАЙТИ(Стр, Подстрока) | позиция первого вхождения, 0 если не найдено | СТРНАЙТИ(Наименование, &Текст) > 0 | 8.3.20 |
ВРЕГ(Стр), НРЕГ(Стр) | верхний и нижний регистр | ВРЕГ(Наименование) | 8.3.20 |
СТРЗАМЕНИТЬ(Стр, Что, НаЧто) | заменяет все вхождения подстроки | СТРЗАМЕНИТЬ(Артикул, "-", "") | 8.3.20 |
СТРОКА(Значение) | значение примитивного типа в строку | СТРОКА(Количество) | 8.3.20 |
Имена не везде совпадают со встроенным языком: длина строки — ДЛИНАСТРОКИ(), а не СтрДлина(), вместо Сред() — ПОДСТРОКА(). У СТРНАЙТИ() в запросе два параметра — где искать и что искать, без направления поиска и номера вхождения. Если конфигурация работает в режиме совместимости ниже 8.3.20, проверьте новые функции в консоли запросов на копии базы.
Отбор, группировку и сортировку по обработанной строке делайте в запросе: обработка в коде после выборки тянет из базы лишние записи.
Строки склеиваются оператором + в любой версии 8.3. Ловушек две.
NULL «съедает» всю строку. Если хотя бы одно слагаемое равно NULL, результат тоже NULL. Типичный источник — поле через точку от пустой ссылки (подробно — в статье про ссылки и поля через точку) или поле правой таблицы левого соединения. Такие слагаемые оборачивайте в ЕСТЬNULL(Поле, "").
Число или дату к строке просто так не прибавить. С 8.3.20 для этого есть функция СТРОКА() в запросе: она переводит значение примитивного типа (число, дату, булево) в текст. Для ссылки берите строковый реквизит, например Контрагент.Наименование. Ниже 8.3.20 выберите число как есть и соберите текст в коде через Формат().
ВЫБРАТЬ
Товары.Ссылка КАК Документ,
ЕСТЬNULL(Товары.Номенклатура.Наименование, "(не указана)")
+ ", " + СТРОКА(Товары.Количество) + " шт." КАК ОписаниеСтроки
ИЗ
Документ.РеализацияТоваровУслуг.Товары КАК Товары
ГДЕ
Товары.Ссылка = &Документ
Имена объектов в примерах условные. Вид результата СТРОКА() зависит от национальных установок, поэтому для файла обмена или ключа сопоставления надёжнее собрать строку в коде через Формат() с явной форматной строкой.
ПОДСТРОКА(Строка, НачальнаяПозиция, Длина) возвращает часть строки. Позиции считаются с единицы, все три параметра обязательны. Результат — строка переменной длины. Если исходное поле неограниченной длины, а длина задана не константой или больше 1024, результат тоже считается неограниченным.
С 8.3.20 для частых случаев есть короткие варианты. ЛЕВ(Документ.Номер, 4) — первые четыре символа, чтобы сгруппировать документы по префиксу номера. ПРАВ(Номенклатура.Артикул, 3) — последние три символа, например код размера в конце артикула.
СТРНАЙТИ(Строка, Подстрока) возвращает позицию первого вхождения или 0, поэтому условие «содержит» выглядит так: СТРНАЙТИ(Номенклатура.Наименование, &Текст) > 0. Регистр функция не учитывает. Одноимённая функция встроенного языка СтрНайти() регистр учитывает, так что одна и та же проверка в запросе и в коде может дать разный результат.
ПОДОБНО работает в любой версии. Служебные символы шаблона: % — любая последовательность символов, _ — один любой символ, [...] — один символ из перечисленных, [^...] — один символ не из перечисленных. Если шаблон собирается из ввода пользователя, служебные символы экранируют через СПЕЦСИМВОЛ, иначе поиск по «100%» или «A_1» найдёт лишнее.
// Экранирует служебные символы шаблона ПОДОБНО спецсимволом "~".
&НаКлиентеНаСервереБезКонтекста
Функция ЭкранироватьДляПодобно(Знач Текст)
Текст = СтрЗаменить(Текст, "~", "~~");
Для Каждого СлужебныйСимвол Из СтрРазделить("%,_,[,],^", ",") Цикл
Текст = СтрЗаменить(Текст, СлужебныйСимвол, "~" + СлужебныйСимвол);
КонецЦикла;
Возврат Текст;
КонецФункции
// Поиск по вхождению: работает на любой версии 8.3.
&НаСервереБезКонтекста
Функция НайтиПоВхождению(Знач СтрокаПоиска)
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ ПЕРВЫЕ 50
| Номенклатура.Ссылка КАК Ссылка
|ИЗ
| Справочник.Номенклатура КАК Номенклатура
|ГДЕ
| Номенклатура.Наименование ПОДОБНО &Шаблон СПЕЦСИМВОЛ ""~""";
Запрос.УстановитьПараметр("Шаблон", "%" + ЭкранироватьДляПодобно(СокрЛП(СтрокаПоиска)) + "%");
Возврат Запрос.Выполнить().Выгрузить().ВыгрузитьКолонку("Ссылка");
КонецФункции
Сам спецсимвол экранируется первым, иначе замены задвоятся; СтрРазделить() есть с 8.3.6. В БСП (как минимум в редакции 3.1) то же делает серверная функция ОбщегоНазначения.СформироватьСтрокуДляПоискаВЗапросе() под спецсимвол ~ — используйте её вместо самописной.
Оборачивать поле и параметр в ВРЕГ() ради сравнения не нужно. По методическим материалам ИТС, в операциях с базой данных строки сравниваются без учёта регистра: это касается =, ПОДОБНО и группировки, а по описанию функций — и СТРНАЙТИ() со СТРЗАМЕНИТЬ(). Во встроенном языке наоборот: "Ф" = "ф" даёт Ложь. Лишний ВРЕГ() вокруг поля ещё и мешает СУБД использовать индекс. ВРЕГ() и НРЕГ() нужны там, где важен вид результата: единый ключ для сверки или колонка отчёта.
СТРЗАМЕНИТЬ(Строка, Что, НаЧто) заменяет все вхождения подстроки, тоже без учёта регистра. Основное применение — привести значение к единому виду перед сравнением: убрать пробелы и дефисы из артикула, скобки из телефона. Пример — поиск дублей контрагентов, у которых наименования отличаются только регистром и пробелами:
ВЫБРАТЬ
СТРЗАМЕНИТЬ(ВРЕГ(Контрагенты.Наименование), " ", "") КАК КлючСравнения,
КОЛИЧЕСТВО(Контрагенты.Ссылка) КАК Карточек
ИЗ
Справочник.Контрагенты КАК Контрагенты
ГДЕ
НЕ Контрагенты.ПометкаУдаления
СГРУППИРОВАТЬ ПО
СТРЗАМЕНИТЬ(ВРЕГ(Контрагенты.Наименование), " ", "")
ИМЕЮЩИЕ
КОЛИЧЕСТВО(Контрагенты.Ссылка) > 1
Здесь ВРЕГ() нужен не для сравнения, а чтобы ключ в результате выглядел одинаково. Следующим шагом выберите сами карточки с найденными ключами — отлаживать такие запросы удобно в консоли запросов.
Условие ДЛИНАСТРОКИ(Контрагенты.ИНН) НЕ В (10, 12) отберёт карточки с ИНН неправильной длины, заодно и незаполненные. СОКРЛП() убирает пробелы по краям. Пригодится, если значение вставили из Excel с пробелом в начале: такое не найдётся ни шаблоном «начинается с», ни сравнением с эталоном.
Функция для формы подбора или обработки: ищет номенклатуру по части наименования или артикула (артикул — без дефисов) и возвращает ссылку и строку для показа. Нужна платформа 8.3.20 и выше.
&НаСервереБезКонтекста
Функция НайтиНоменклатуру(Знач СтрокаПоиска)
Найденные = Новый Массив;
СтрокаПоиска = СокрЛП(СтрокаПоиска);
АртикулБезДефисов = СтрЗаменить(СтрокаПоиска, "-", "");
Если СтрДлина(АртикулБезДефисов) < 2 Тогда
Возврат Найденные;
КонецЕсли;
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ ПЕРВЫЕ 50
| Номенклатура.Ссылка КАК Ссылка,
| ВЫБОР
| КОГДА СОКРЛП(Номенклатура.Артикул) = """"
| ТОГДА Номенклатура.Наименование
| ИНАЧЕ Номенклатура.Наименование + "" (арт. "" + СОКРЛП(Номенклатура.Артикул) + "")""
| КОНЕЦ КАК Описание
|ИЗ
| Справочник.Номенклатура КАК Номенклатура
|ГДЕ
| НЕ Номенклатура.ПометкаУдаления
| И НЕ Номенклатура.ЭтоГруппа
| И (СТРНАЙТИ(Номенклатура.Наименование, &Текст) > 0
| ИЛИ СТРНАЙТИ(СТРЗАМЕНИТЬ(Номенклатура.Артикул, ""-"", """"), &АртикулБезДефисов) > 0)
|
|УПОРЯДОЧИТЬ ПО
| ДЛИНАСТРОКИ(Номенклатура.Наименование),
| Номенклатура.Наименование";
Запрос.УстановитьПараметр("Текст", СтрокаПоиска);
Запрос.УстановитьПараметр("АртикулБезДефисов", АртикулБезДефисов);
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
Найденные.Добавить(Новый Структура("Ссылка, Описание", Выборка.Ссылка, Выборка.Описание));
КонецЦикла;
Возврат Найденные;
КонецФункции
Разбор ключевых строк:
СокрЛП() и проверка длины — в коде, до запроса.СТРНАЙТИ(Номенклатура.Наименование, &Текст) > 0 — «содержит» без учёта регистра и без экранирования, которое нужно для ПОДОБНО.СТРЗАМЕНИТЬ(Номенклатура.Артикул, "-", "") и параметр, очищенный так же в коде, — «АБ-123», «АБ123» и «аб-123» найдутся одинаково.НЕ Номенклатура.ЭтоГруппа — только товары, без папок; у справочника без групп условие уберите.ВЫБОР в поле Описание убирает пустые скобки у товаров без артикула.УПОРЯДОЧИТЬ ПО ДЛИНАСТРОКИ(...) — сначала короткие наименования: при поиске «кабель» элемент «Кабель» окажется выше, чем «Кабель-канал белый».&НаСервереБезКонтекста: запрос на клиенте не выполнить, а данные формы не нужны.Ниже 8.3.20 замените условие на ПОДОБНО с экранированием из раздела выше и уберите СОКРЛП() и сортировку по длине; поиск артикула без дефисов тогда не сделать.
Реквизиты вроде «Комментарий» обычно имеют тип Строка с длиной 0, то есть неограниченной длины. Такое поле в запросе нельзя:
=, <>, В или в условии соединения;СГРУППИРОВАТЬ ПО;РАЗЛИЧНЫЕ и объединять через ОБЪЕДИНИТЬ без ВСЕ: дубли там убираются тем же сравнением.Стандарт 1С «Использование реквизитов строкового типа» в таких случаях требует приводить поле к строке определённой длины и рекомендует для этого ВЫРАЗИТЬ(Поле КАК СТРОКА(N)). Приведение через ПОДСТРОКА(Поле, 1, N) методическая статья ИТС не рекомендует: на MS SQL Server длина её результата в некоторых выражениях вычисляется как 4000 символов, и сортировка по двум таким полям падает с ошибкой СУБД о превышении 8000 байт. Символы после N-го в сравнении не участвуют.
ВЫБРАТЬ
ВЫРАЗИТЬ(Заказ.Комментарий КАК СТРОКА(200)) КАК Комментарий,
КОЛИЧЕСТВО(Заказ.Ссылка) КАК Документов
ИЗ
Документ.ЗаказКлиента КАК Заказ
ГДЕ
Заказ.Проведен
И ВЫРАЗИТЬ(Заказ.Комментарий КАК СТРОКА(200)) <> ""
СГРУППИРОВАТЬ ПО
ВЫРАЗИТЬ(Заказ.Комментарий КАК СТРОКА(200))
УПОРЯДОЧИТЬ ПО
Документов УБЫВ
Для остальных операций приводить поле не нужно: выбрать его или отобрать через ПОДОБНО можно как есть. В отчёте на СКД вместо ВЫРАЗИТЬ можно задать полю тип значения на закладке «Наборы данных».
СтрДлина(), Сред(), СтрЧислоВхождений() в запросе не существуют. Запрос не пройдёт проверку синтаксиса, платформа укажет место ошибки в формате {(строка, колонка)}.ЕСТЬNULL().СТРОКА().ВЫРАЗИТЬ(Поле КАК СТРОКА(N)).% и _ из текста работают как шаблон.""-"". Лишняя кавычка обрывает строку — это уже ошибка компиляции модуля.На 8.3.20 и выше — СТРНАЙТИ(Поле, &Текст) > 0. На старых версиях — Поле ПОДОБНО &Шаблон с шаблоном "%" + текст + "%". Оба варианта регистр не различают, так что ВРЕГ() с обеих сторон условия не нужен.
С 8.3.20 — функцией СТРОКА(). На более ранних версиях выберите значение как есть и соберите текст в коде через Формат(). Сравнивать и группировать даты лучше как даты, а не как строки, — подробнее в статье о датах в запросе.
Агрегатной функции для соединения строк в языке запросов нет. Соберите строку в коде при обходе выборки или, если это отчёт на СКД, используйте в выражении ресурса функции языка выражений СКД СоединитьСтроки() и Массив().
В запросе набора данных — да, с теми же требованиями к версии. В вычисляемых полях и ресурсах работает язык выражений СКД; одноимённые функции (ДлинаСтроки, СтрНайти, СтрЗаменить и другие) добавили туда в той же версии 8.3.20.
Условие «содержит» — СТРНАЙТИ(...) > 0 или ПОДОБНО "%текст%" — СУБД выполняет перебором записей: функция от поля не даёт использовать индекс. Сузьте выборку условиями по периоду, организации, виду номенклатуры. Шаблон «начинается с» (ПОДОБНО "текст%") СУБД обычно выполняет по индексу. Для больших объёмов текста есть полнотекстовый поиск платформы.
Если поиск, сверка или отчёт со строковыми условиями нужны срочно, а конфигурация сильно доработана или стоит на старой платформе, проще отдать задачу программисту. Отчёты на СКД и обработки поиска и сверки — в услуге отчёты и обработки 1С. Опишите задачу на странице «Разместить задание» — оценка бесплатная, ответ в течение рабочего дня.
Станьте частью сообщества!
Войдите или зарегистрируйтесь, и вы сможете участвовать в обсуждениях.