Как сделать отбор по пользовательскому реквизиту справочника через 1sqlite в 1С 7.7

Программист 1С v7.7 IT и автоматизация бизнеса
← На главную

При оптимизации скорости поиска в объемных справочниках платформы 1С:Предприятие 7.7 часто прибегают к прямым запросам с помощью внешней компоненты 1sqlite. Типовой сценарий — контекстный поиск подстроки по нескольким словам в наименовании элемента. Однако при попытке переключить отбор со стандартного наименования на добавленный реквизит (например, Артикул, НомерТелефона или Комментарий) разработчики нередко сталкиваются с ошибками выполнения запроса. Выясним причину такого поведения и разберем по шагам, как правильно адресовать реквизиты в виртуальных таблицах 1sqlite.

В чем заключалась проблема

Рассмотрим исходную ситуацию: в справочнике контактных лиц или номенклатуры реализован поиск по наименованию (системному полю descr) с разбиением введенной поисковой фразы на отдельные слова:


РазбиваемаяСтрока = СтрЗаменить(РазбиваемаяСтрока, "'", "''");
РазбиваемаяСтрока = СтрЗаменить(СокрЛП(стрПоиска), " ", РазделительСтрок);
текст = "SELECT
        |code Код,
        |id [КонтактноеЛицо :Справочник.КонтактныеЛица]
        |FROM КонтЛица
        |WHERE ismark <> '*'";
Для Индекс = 1 По СтрКоличествоСтрок(РазбиваемаяСтрока) Цикл
    Слово = СтрПолучитьСтроку(РазбиваемаяСтрока, Индекс); 
    Если ПустоеЗначение(Слово) = 0 Тогда
        текст = текст + "
                |AND descr LIKE '%" + Слово + "%'";
    КонецЕсли;
КонецЦикла;

При необходимости искать данные по новому добавленному реквизиту возникает соблазн заглянуть в структуру файлов базы данных через просмотрщик DBF или файл описания 1cv7.dd. Обнаружив физическое имя колонки (например, SP12547), программист подставляет его вместо descr, но запрос завершается ошибкой.

Почему не работают имена полей DBF вида SPxxxxx

Проанализируем архитектуру работы компоненты. Модуль dbeng, отвечающий за связь SQLite с таблицами 1С 7.7, строит виртуальные таблицы на основе метаданных конфигурации, а не прямой трансляцией низкоуровневых имен DBF. Это означает следующее:

  1. Имена системных полей: Для стандартных реквизитов используются зарезервированные имена SQLite: id (ссылка на объект), code (код элемента), descr (наименование), ismark (пометка на удаление, содержащая символ звездочки *), isfolder (признак папки), parentid (родительская группа) и parentext (владелец).
  2. Имена пользовательских реквизитов: Все реквизиты, добавленные разработчиком в конфигураторе, проецируются в виртуальную таблицу под своими реальными идентификаторами из дерева метаданных. Служебные имена вида SP12547 компонента переопределяет автоматически и в теле запроса их не распознает.

Правильное построение запроса по реквизиту

Для фильтрации по пользовательскому полю достаточно указать его точное имя так, как оно задано в конфигураторе 1С. Посмотрим на пример, когда требуется искать совпадение либо в наименовании, либо в реквизите Артикул:


Для Индекс = 1 По СтрКоличествоСтрок(РазбиваемаяСтрока) Цикл
    Слово = СтрПолучитьСтроку(РазбиваемаяСтрока, Индекс); 
    Если ПустоеЗначение(Слово) = 0 Тогда
        текст = текст + "
                |AND (descr LIKE '%" + Слово + "%' OR Артикул LIKE '%" + Слово + "%')";
    КонецЕсли;
КонецЦикла;

Если поиск требуется вести исключительно по добавленному реквизиту, просто заменяем descr на его имя из метаданных:


текст = текст + "
        |AND НомерТелефона LIKE '%" + Слово + "%'";

Ограничения и важные нюансы при работе с типами данных

Разберем специфические особенности, которые необходимо учитывать при выборках через 1sqlite:

  1. Периодические реквизиты: Значения периодических реквизитов в 1С 7.7 хранятся отдельно от справочника — в таблице истории _1SCONST. В виртуальной таблице справочника колонка периодического реквизита отсутствует. Обычный отбор Реквизит LIKE ... к ним применить нельзя — потребуется связывание (LEFT JOIN) с таблицей _1SCONST и получение среза последних значений.
  2. Ссылочные реквизиты: Если реквизит имеет тип «Справочник», «Документ» или «Перечисление», в таблице физически хранится текстовый идентификатор объекта (ID). Поиск через LIKE '%...%' будет выполняться по внутреннему коду ссылки, а не по её представлению. Чтобы искать по наименованию связанного объекта, необходимо присоединять соответствующую таблицу справочника по равенству Реквизит = Справочник2.id.
  3. Регистронезависимость и пробелы: По умолчанию оператор LIKE в базовом SQLite корректно обрабатывает регистр только для латиницы. В компоненте 1sqlite встроен модификатор сопоставления COLLATE _1C, обеспечивающий корректное сравнение кириллических строк и отсечение завершающих пробелов для строковых реквизитов фиксированной длины.
  4. Производительность: Шаблон вида '%текст%' неизбежно приводит к полному сканированию таблицы (Full Scan), так как индексные файлы .cdx не могут быть использованы при наличии знака процента в начале строки поиска. На базах с сотнями тысяч элементов такой запрос может вызывать задержки. Если допустим поиск только по началу строки ('текст%'), компонента сможет задействовать существующие индексы отбора и сортировки.
← На главную