Как в 1С найти элементы справочника или документа по нескольким реквизитам?

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

При разработке на платформе 1С очень часто возникает задача поиска конкретного документа или элемента справочника сразу по нескольким условиям. Многие разработчики, приходящие в 1С из других языков программирования, удивляются отсутствию простого метода вроде Найти(Поле1 = Значение1 И Поле2 = Значение2). Рассмотрим подробнее, как правильно решать эту задачу, проанализируем доступные инструменты и выясним причину, по которой архитектура 1С устроена именно так.

Поиск по нескольким реквизитам через объектную модель (без запроса)

Для начала разберем ситуацию, когда писать полноценный запрос кажется избыточным, и хочется обойтись встроенными методами менеджера объекта. В платформе действительно есть штатный механизм для простого поиска по совпадению нескольких полей.

Воспользуемся методом менеджера Выбрать(). В этот метод в качестве параметра (обычно это третий параметр) можно передать объект Структура. Платформа самостоятельно отфильтрует данные и вернет только те записи, которые одновременно удовлетворяют всем переданным условиям. То есть, между ключами структуры неявно сработает логическое условие "И".

Посмотрим на пример реализации такого поиска:


Отбор = Новый Структура;
Отбор.Вставить("Организация", ИскомаяОрганизация);
Отбор.Вставить("Контрагент", ИскомыйКонтрагент);

Выборка = Документы.РеализацияТоваровУслуг.Выбрать( , , Отбор);
Пока Выборка.Следующий() Цикл
    // Обработка найденного документа
    Сообщить(Выборка.Ссылка);
КонецЦикла;

Важные ограничения данного метода: метод поддерживает только проверку на строгое равенство. Если нам нужно найти значения с условиями "больше", "меньше", "не равно" или использовать логическое "ИЛИ", то объектная модель нам не поможет. В таких случаях необходимо переходить к написанию запроса.

Использование языка запросов для поиска (Оптимальный вариант)

Разберем по шагам, почему использование запросов является "золотым стандартом" в 1С. Как отмечают опытные специалисты, запрос будет выполняться значительно быстрее. При использовании объектной модели платформа тянет из базы данных SQL абсолютно все реквизиты объекта, а также данные всех его табличных частей. Если в документе десятки реквизитов и огромная табличная часть, чтение одного такого объекта сильно нагрузит сеть и сервер.

Запрос же считывает только те конкретные колонки, которые вы запросили, и делает это за доли секунды. Посмотрим на классический пример поиска документа по номеру и дате с помощью запроса:


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

Запрос.УстановитьПараметр("Номер", ИскомыйНомер);
Запрос.УстановитьПараметр("Дата", ИскомаяДата);

РезультатЗапроса = Запрос.Выполнить();

Если Не РезультатЗапроса.Пустой() Тогда
    Выборка = РезультатЗапроса.Выбрать();
    Выборка.Следующий();
    Возврат Выборка.Ссылка;
Иначе
    Возврат Неопределено;
КонецЕсли;

Этот подход менее трудоемок для сервера базы данных и позволяет гибко управлять условиями отбора (например, выполняя сравнение строки с представлением ссылки в запросе или добавляя сложные логические связки).

Сложный поиск по связкам значений (Тройки данных)

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

Писать в запросе длинную портянку из условий вида (Орг = &Орг1 И Контр = &Контр1) ИЛИ (Орг = &Орг2 И Контр = &Контр2) — плохая практика. В 1С эта задача решается очень изящно с помощью передачи таблицы значений в запрос.

Выполним следующие шаги для реализации:

  1. Создадим программную ТаблицаЗначений с тремя колонками: Организация, Контрагент, Комментарий.
  2. Заполним эту таблицу нужными уникальными комбинациями для поиска.
  3. Передадим эту таблицу в объект Запрос в качестве параметра.
  4. В тексте запроса поместим эту таблицу во временную таблицу.
  5. Сделаем внутреннее соединение (INNER JOIN) таблицы документов с нашей временной таблицей по всем трем полям.

Посмотрим на пример кода, реализующий этот элегантный подход:


// 1. Подготовка таблицы условий
ТаблицаУсловий = Новый ТаблицаЗначений;
ТаблицаУсловий.Колонки.Добавить("Организация");
ТаблицаУсловий.Колонки.Добавить("Контрагент");
ТаблицаУсловий.Колонки.Добавить("Комментарий");

// Заполнение данными (пример для одной строки)
НоваяСтрока = ТаблицаУсловий.Добавить();
НоваяСтрока.Организация = Орг1;
НоваяСтрока.Контрагент = Контр1;
НоваяСтрока.Комментарий = "Дог1, сч1";

// 2. Выполнение запроса
Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |    ТаблицаУсловий.Организация,
    |    ТаблицаУсловий.Контрагент,
    |    ТаблицаУсловий.Комментарий
    |ПОМЕСТИТЬ ВТУсловия
    |ИЗ
    |    &ТаблицаУсловий КАК ТаблицаУсловий
    |;
    |
    |////////////////////////////////////////////////////////////////////////////////
    |ВЫБРАТЬ
    |    Документ.Ссылка
    |ИЗ
    |    Документ.РеализацияТоваровУслуг КАК Документ
    |        ВНУТРЕННЕЕ СОЕДИНЕНИЕ ВТУсловия КАК ВТУсловия
    |        ПО Документ.Организация = ВТУсловия.Организация
    |            И Документ.Контрагент = ВТУсловия.Контрагент
    |            И Документ.Комментарий = ВТУсловия.Комментарий";

Запрос.УстановитьПараметр("ТаблицаУсловий", ТаблицаУсловий);
Результат = Запрос.Выполнить().Выгрузить();

В результате сервер баз данных моментально отфильтрует огромный массив информации и вернет только те документы, которые строго соответствуют нужным сложным комбинациям данных.

Почему в языке запросов 1С нет UPDATE, INSERT и DELETE?

Часто специалисты по SQL возмущаются, почему в 1С нельзя просто написать DELETE FROM Документ или сделать быстрый UPDATE. Выясним причину этой архитектурной особенности.

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

  1. Отрабатывают обработчики событий (ПередЗаписью, ПриЗаписи, ОбработкаПроведения).
  2. Платформа выполняет проверку заполненности обязательных полей.
  3. Происходит сложный контроль остатков на складах и взаиморасчетов.
  4. Формируются записи движений в зависимые регистры (бухгалтерия, регистры накопления, регистры сведений) — для проверки их корректности есть инструмент для диагностики и очистки регистров.

Если бы платформа позволяла делать прямые запросы на изменение данных, вся эта бизнес-логика была бы проигнорирована. Это моментально привело бы к разрушению ссылочной целостности базы данных, появлению "битых" ссылок (если это уже произошло, поможет готовая обработка для удаления битых ссылок) и разъезжанию остатков. Поэтому в 1С чтение данных сделано быстрым (через SELECT в запросах), а изменение данных реализовано строго пообъектно: мы должны получить объект, изменить его свойства и выполнить метод Записать(). Только так система гарантирует корректность всех взаимосвязанных данных в учете.

← На главную