Руководство администратора

  1. Главная
  2. Документы
  3. Руководство администратора
  4. Глоссарий
  5. Подобно (Like) в 1С

Подобно (Like) в 1С

Среди прочих инструментов, предоставляемых механизмом запросов 1С (который, как мы знаем, есть насадка-транслятор на механизмы СУБД), имеется единственный в своём роде — наложение условия шаблоном. Большинство операций реляционных СУБД работают с точными значениями или их диапазонами, и только ПОДОБНО имеет дело с маской, нечётким условием. «ПОДОБНО», он же «LIKE», есть в подавляющем большинстве современных СУБД (согласно стандарту ANSI SQL 2003), и 1С предоставляет нам возможности такого поиска единообразно, приводя средствами платформы различные тонкости СУБД к единому поведению. Возможность эта заложена в механизме запросов, отборов, отборов СКД (во всех её проявлениях), и, как показывает практика, «ПОДОБНО» действительно ведёт себя совершенно одинаково и ожидаемо и в динамических списках, и в разных запросах — везде в 1С.

Нам известны более кастомизированные механизмы — отборы и отборы СКД «Содержит»/»Не содержит». По сути они реализованы тем же образом, что и ПОДОБНО, но урезаны, и формируют строку шаблона самостоятельно (дописывают «%»). Тому есть несколько причин, от защиты ключевых мест системы от действий пользователя и разработчика, провоцирующих избыточную нагрузку, до простоты реализации в платформе.

Нам известны более гибкие механизмы — это полнотекстовый поиск. Он в СУБД реализуется отдельно от «основного движка», требует свои конструкции, индексы, и «может всё» ценой накладных расходов на разработку и поддержание. Известны также регулярные выражения и т.д.

Поиск «ПОДОБНО» опирается на штатную работу СУБД, на обращения к колонкам фактографической реляционной БД, пусть даже они строкового типа неограниченной длины. Обработка отбора «ПОДОБНО» обычно не требует специальных донастроек ни в 1С, ни в СУБД.

  Из справки 1С (синтакс-помощник)

Оператор ПОДОБНО позволяет сравнить значение выражения, указанного слева от него, со строкой шаблона, указанной справа. Значение выражения должно иметь тип строка. Если значение выражения удовлетворяет шаблону – результатом оператора будет ИСТИНА, иначе – ЛОЖЬ.
Следующие символы в строке шаблона являются служебными и имеют смысл, отличный от символа строки:
% (процент): последовательность, содержащая любое количество произвольных символов.
_ (подчеркивание): один произвольный символ.
[…] (в квадратных скобках один или несколько символов): любой одиночный символ из перечисленных внутри квадратных скобок.
В перечислении могут встречаться диапазоны, например a-z, означающие произвольный символ, входящий в диапазон, включая концы диапазона.
[^…] (в квадратных скобках значок отрицания, за которым следует один или несколько символов): любой одиночный символ, кроме тех, которые перечислены следом за значком отрицания.
Любой другой символ означает сам себя и не несет никакой дополнительной нагрузки.
Если в качестве самого себя необходимо записать один из перечисленных символов, то ему должен предшествовать <Спецсимвол>. Сам <Спецсимвол> (любой подходящий символ) определяется в этом же операторе после ключевого слова СПЕЦСИМВОЛ.

Особенности использования в запросах оператора ПОДОБНО (ИТС)

#std726

Область применения: управляемое приложение, мобильное приложение, обычное приложение.

1. Оператор ПОДОБНО в тексте запроса необходимо использовать только

  • с константным строковым литералом, например:
    Реквизит ПОДОБНО «123%»
  • с параметром запроса, например:
    Реквизит ПОДОБНО &Шаблон

Не следует формировать строку шаблона вычислениями или конкатенацией.

Правильно:

Реквизит ПОДОБНО «123%»
Реквизит ПОДОБНО &Шаблон

Неправильно:

Реквизит ПОДОБНО «123» + «%»
Реквизит ПОДОБНО &Шаблон + «%»
Реквизит ПОДОБНО Таблица.Шаблон

2. При разработке конфигурации необходимо использовать такие шаблоны для оператора ПОДОБНО, которые одинаково работают на всех СУБД, поддерживаемых платформой 1С:Предприятие:

  • % (процент) – последовательность, содержащая любое количество произвольных символов;
  • _ (подчеркивание) – один произвольный символ.

Недопустимы, т.к. не работает на IBM DB 2:

  • […] (в квадратных скобках один или несколько символов) – любой одиночный символ из перечисленных внутри квадратных скобок. В перечислении могут встречаться диапазоны, например a-z, означающие произвольный символ, входящий в диапазон, включая концы диапазона;
  • [^…] (в квадратных скобках значок отрицания, за которым следует один или несколько символов) – любой одиночный символ, кроме тех, которые перечислены следом за значком отрицания.

При разработке прикладных решений необходимо учитывать все ограничения, чтобы обеспечивать работу на всех СУБД, поддерживаемых платформой 1С:Предприятие (см. документацию к платформе 1С:Предприятие):

  • Длина строки шаблона не должна превышать 1024 символа (ограничение MS SQL 2005).

3. Необходимо экранировать все спецсимволы (_%[]^), чтобы они трактовались как часть искомого текста (а не как спецсимвол). Иначе если пользователь в строке поиска, например, введет текст со скобками [ ], то при выполнении запроса возникнет ошибка вида: ERROR:  invalid regular expression: invalid character range (PostgreSQL).

Для экранирования необходимо:

  • выбрать спецсимвол экранирования, например (~);
  • установить спецсимвол перед символами операнда, например (~%). Чтобы экранировать выбранный спецсимвол, его необходимо задвоить, например (~~).
  • и дополнить шаблон ключевым словом СПЕЦСИМВОЛ.

Например, для поиска по строке «100%»:

«100~%» СПЕЦСИМВОЛ «~»

При этом нужно иметь в виду, что установка параметров запроса с помощью Запрос.УстановитьПараметр не экранирует спецсимволы шаблона для ПОДОБНО. Для экранирования спецсимволов в конфигурациях с Библиотекой стандартных подсистем (БСП) рекомендуется вызывать процедуру ОбщегоНазначения.СформироватьСтрокуДляПоискаВЗапросе.

Правильно:

ВЫБРАТЬ
Номенклатура.Ссылка КАК Ссылка
ИЗ
Справочник.Номенклатура КАК Номенклатура
ГДЕ
Номенклатура.Наименование ПОДОБНО &Шаблон СПЕЦСИМВОЛ «~»

Запрос.УстановитьПараметр(«Шаблон», «%» + ОбщегоНазначения.СформироватьСтрокуДляПоискаВЗапросе(ИскомыйТекст) + «%»);

Реализация для конфигураций без Библиотеки стандартных подсистем (БСП):

Функция СформироватьСтрокуДляПоискаВЗапросе(Знач СтрокаПоиска) Экспорт

Результат = СтрокаПоиска;
Результат = СтрЗаменить(Результат, «~», «~~»);
Результат = СтрЗаменить(Результат, «%», «~%»);
Результат = СтрЗаменить(Результат, «_», «~_»);
Результат = СтрЗаменить(Результат, «[«, «~[«);
Результат = СтрЗаменить(Результат, «]», «~]»);
Результат = СтрЗаменить(Результат, «^», «~^»);

Возврат Результат;

КонецФункции

4. Сравнение выполняется без учета регистра символов.

Операторы «классического» поиска:

У метода ПОДОБНО в запросах 1С:Предприятия есть несколько операторов, которые позволяют осуществлять поиск с использованием более сложных шаблонов. Операторы для использования с методом ПОДОБНО: 1. % — Заменяет любое количество символов (0 или более символов). Например, "Тов%" будет соответствовать значению "Товар", "Товары", "Товарная" и т.д. 2. _ — Заменяет один любой символ. Например, "Товар_" будет соответствовать значению "Товары", но не «Товар» или «Товарная». 3. [] — Определяет диапазон символов. Например, "Товар[0-9]" будет соответствовать значениям "Товар0", "Товар1", "Товар2", и т.д. 4. [^] — Отрицание диапазона символов. Например, "Товар[^0-9]" будет соответствовать значениям "Товар", "Товара", и т.д., но не "Товар0" или "Товар1". 5. ^ — Определяет начало строки. Например, "Товар^" будет соответствовать значениям, которые начинаются с «Товар», например, "Товарный отдел". 6. $ — Определяет конец строки. Например, "$овар" будет соответствовать значениям, которые оканчиваются на «овар», например, "Товар". Это лишь некоторые из операторов, которые можно использовать с методом ПОДОБНО в запросах 1С:Предприятия. Вам также доступны стандартные символы замены, такие как ? для замены одного символа и * для замены нуля или более символов.

// имеем запрос вида:
ТекстЗапроса="ВЫБРАТЬ Истина ИЗ Справочник.Сайты КАК спр ГДЕ спр.Наименование ПОДОБНО &Условие";
// и элемент справочника с наименованием "Инфостарт".
//
// в зависимости от успешности поиска Запрос.Выполнить().Пустой() будет Истина (не нашли) или Ложь (нашли)
// служебный символ "%"
Запрос.УстановитьПараметр("Условие","%фоста%"); // найдёт
Запрос.УстановитьПараметр("Условие","%фоста"); // не найдёт
Запрос.УстановитьПараметр("Условие","%фостарт"); // найдёт
Запрос.УстановитьПараметр("Условие","Инфоста%"); // найдёт
Запрос.УстановитьПараметр("Условие","Инфоста"); // не найдёт
Запрос.УстановитьПараметр("Условие","Ин%арт"); // найдёт
// служебный символ "_"
Запрос.УстановитьПараметр("Условие","_Инфостарт"); // не найдёт
Запрос.УстановитьПараметр("Условие","_нфостарт"); // найдёт
Запрос.УстановитьПараметр("Условие","Инфостар_"); // найдёт
Запрос.УстановитьПараметр("Условие","Инфоста_"); // не найдёт
Запрос.УстановитьПараметр("Условие","Ин_оста_т"); // найдёт

Операторы с квадратными скобками позволяет понять, «есть ли такая буква в этом слове». Например:

Запрос.УстановитьПараметр("Условие","Ин[клм]остарт"); // не найдёт
Запрос.УстановитьПараметр("Условие","Ин[фыва]остарт"); // найдёт
// можно чередовать и применять всё вместе:
Запрос.УстановитьПараметр("Условие","И%[фыва]_ст[^йоу]р%"); // найдёт

Также, согласно стандарту, квадратные скобки «понимают» диапазоны букв:

Запрос.УстановитьПараметр("Ин[т-х]остарт"); // определяем буквы "т, у, ф, х", найдёт
Запрос.УстановитьПараметр("Ин[б-д]остарт"); // определяем буквы "б, в, г, д", не найдёт

// можно перечислять и указывать диапазоны вперемешку:
Запрос.УстановитьПараметр("Ин[рст-ц]остарт"); // определяем буквы "р, с, т, у, ф, х, ц", найдёт

То же касается отрицаний [^..], можно задавать диапазоны символов. Напомню, порядок определяется возрастанием числовых кодов символов в таблице кодировки. При нарушенном порядке [я-а] ничего не найдётся. Сами квадратные скобки тоже можно искать: «[[]» определяет символ «[«. Символы «%» и «_» в скобках означают сами себя, а не служебные wildcard.

Сложный шаблон уже даже начинает напоминать регулярное выражение. «ПОДОБНО» реализует упрощённую wildcard-семантику, где «%» заменяет классический «*», а «_» заменяет классический «?».

  • Многократный повтор «%» ровно ничего не меняет, «%%%фостарт», «Ин%%%%т» и «%фостарт» равнозначны. А вот «_» требователен к знакоместам, к позициям, и следует быть внимательным к повторам, т.к. «__нфостарт» сработает, а «___нфостарт» нет.
  • Все операторы не чувствительны к регистру букв, «Инф%» и «инф%» равнозначны. Интересно, что SQL по умолчанию тоже не учитывает регистр, а PostgreSQL и Оракл — учитывают.
  • Все операторы корректно обрабатывают всяческие символы, т.е. коллекцию «Символы», и символ параграфа-конца страницы, и прочий мусор (есть тонкости в национальных частях кодировок, см.ниже). В том числе в конструкциях «[..] и [^..]. Такие могут фигурировать в наполнении таблицы, в условии запроса, и будут правильно найдены (ввести их в строку поиска можно программно или скопипастить откуда-нибудь). «Символ.ПС», несмотря на некоторую синтетичность CR+LF, это один символ.
  • Сами себя «%» и «_» правильно находят, на общих основаниях, т.е. «Доход 20% годовых» по «%д 20% г%» будет найден.
  • Не следует делать экранирование операторов, как принято в СУБД, т.е. «/%» как раз-таки не сработает. Для экранирования и для уточнения используется оператор «СПЕЦСИМВОЛ» (он же Escape):
// имеем запрос вида:
ТекстЗапроса="ВЫБРАТЬ Истина ИЗ Справочник.Сайты КАК спр ГДЕ спр.Наименование ПОДОБНО &Условие";

// надо найти именно элемент с наименованием "Инфостарт_Сайт", а не "Инфостарт Сайт"
// поиск по шаблону "Инфостарт_Сайт" выдаст оба элемента. 

Поэтому следует изменить запрос:
ТекстЗапроса="ВЫБРАТЬ Истина ИЗ Справочник.Сайты КАК спр ГДЕ спр.Наименование ПОДОБНО &Условие" СПЕЦСИМВОЛ""$""";
// поиск по шаблону "Инфостарт$_Сайт" выдаст только нужное.

 

Поиск возможен в строковых полях таблиц (в т.ч. неограниченной длины), в переменных неограниченной длины (в т.ч. полях таблиц-параметров и временных таблиц). Но при этом поиск невозможен в полях, полученных функцией «ПредставлениеСсылки», или имеющих, явно или потенциально, значение Null. Если таковое явственно, то даже компиляция, в т.ч. открытие конструктора запроса/СКД, сообщает об ошибке «Неверные параметры», если же нет, то будет ошибка исполнения запроса.

Отбор средствами СКД для «ПОДОБНО» имеет дело с значением колонки таблицы и может использовать индексы, т.е. быть ускорен (в SQL и Oracle так и есть), и создаваемая им нагрузка наблюдаема в профайлере обычным образом. Замечено, что запрос на несколько значений одного и того же поля «спр.Путь ПОДОБНО «»%фостар%»» ИЛИ спр.Путь ПОДОБНО «»%тар_»» и т.д., оптимизируется почти всегда, поэтому опасаться критичного торможения при наложении условия, моделирующего «подобие в списке» для одного поля, не стоит. А вот условия на разные поля, конечно, дадут рост нагрузки и, возможно, мер по оптимизации запроса.

  О кодировках

Определённую тонкость представляет кодировка. 1С использует Unicode, и вроде бы защищает нас от специфики СУБД, но, поскольку есть «Внешние источники», запросы и СКД к ним, упомяну о кодировке.

В MS SQL понимание кодировки зависит от SSMS, стыковки сервера скуля с провайдером, правильно выставленного свойства БД Collation (Cyrillic_General_CI_AS). Иногда where f1 like ‘%нфост%’ не работает, а where f1 like N’%нфост%’ работает, т.е. стоит перед литеральными юникодными строками писать «N» или делать так: «f1 LIKE Convert(VarChar,N’%нфост%’)». Также советуют для юникода применять функции NCHAR(), UNICODE() и т.д, а не CHAR(), ANSI() и т.д. SQL иначе учитывает завершающие пробелы, и с кодировкой ASCII работает по своим старым стандартам, а не по ISO.

В Оракле: есть просто разные операторы:
«обычный» LIKE — применяется для запроса к строковым столбцам с традиционными кодировками;
LIKEC — применяется для столбцов с кодировкой Unicode (в терминологии Oracle — Unicode complete);
LIKE2 — для кодировки UCS2;
LIKE4 — для кодировки UCS4.

Насчёт внешних источников в методическом описании 1С сказано:
«Строковые функции и выражения запроса и СКД преобразуются в запрос к СУБД с использованием управляющих последовательностей ODBC (ODBC Escape Sequences, http://msdn.microsoft.com/en-us/library/windows/desktop/ms715364(v=vs.85).aspx», причём там речь о функции «Подстрока», а «ПОДОБНО» не упомянут вообще нет, но на практике эффект тот же. В других статьях 1С на эту тему никакие ограничения вообще не упомянуты.

И, повторюсь, благодаря 1С в «классических» случаях мы можем не заботиться о кодировке. 1С найдёт даже кракозябр в строке ему подобных.

  Примечания

Часть возможностей «ПОДОБНО» можно смоделировать, используя схожий инструмент — функцию «Подстрока», например:

// вместо
ТекстЗапроса=»ВЫБРАТЬ Истина ИЗ Справочник.Сайты КАК спр ГДЕ спр.Наименование ПОДОБНО «»Инфо%»»»;
// можно
ТекстЗапроса=»ВЫБРАТЬ Истина ИЗ Справочник.Сайты КАК спр ГДЕ Подстрока(спр.НаименованиеПодстрока,1,4) = «Инфо»;

Но делать это не стоит. И в 1С, и в основных СУБД поиск «Like» обычно быстрее «Substr», т.к. поиск по колонке, могущей иметь (и часто имеющей) индекс быстрее, чем вычисление произвольного выражения в функции. Однако, в «продвинутых» случаях, с помощью т.н. «function-based index» и особо крутой статистики оптимизатор запроса СУБД может-таки заставить вычисление подстроки работать почти так же быстро. Но зачем?..

Отличается и поведение. В отличие от «ПОДОБНО», функция «Подстрока» может обработать Null, и её результатом тоже будет Null; но «ПредставлениеСсылки» она тоже не обрабатывает.

Был ли данный материал полезен вам? Да Нет