Разработка и Конфигурация · 12 мин
Как сделать выборку из справочника в 1С
Как сделать выборку из справочника в 1С: запрос с условиями, методы Выбрать() и НайтиПоКоду(), отбор по владельцу, обход иерархии, типичные ошибки и примеры кода.
Выборка из справочника — базовая операция при доработке конфигураций 1С: она нужна для отчётов, обработок, обменов данными и проверок заполнения. Существует два принципиально разных подхода: запрос на встроенном языке запросов и объектные методы типа Выбрать(). Первый быстрее и гибче, второй проще для понимания новичками, но медленнее при больших объёмах.
Правильный выбор способа зависит от задачи. Если нужно получить тысячи элементов для отчёта — используйте запрос. Если нужно найти один элемент по коду или наименованию и изменить его — подойдут методы НайтиПоКоду() или НайтиПоНаименованию(). Ниже разобраны оба подхода с рабочими примерами кода, условиями отбора и типичными ошибками.
Какие способы выборки существуют и когда какой применять
В платформе 1С:Предприятие доступны три основных механизма получения данных справочника. Первый — запрос: декларативный способ, при котором сервер базы данных сам выбирает нужные записи и возвращает только их. Второй — метод Выбрать() менеджера справочника, который возвращает объект выборки для последовательного перебора. Третий — точечный поиск методами НайтиПоКоду(), НайтиПоНаименованию(), НайтиПоРеквизиту().
Запрос почти всегда предпочтительнее: он выполняется на стороне СУБД, позволяет отобрать только нужные поля, соединить несколько таблиц и посчитать итоги. Метод Выбрать() оправдан в простых сценариях, когда нужно перебрать небольшое количество элементов, а читаемость кода важнее скорости. Точечный поиск — единственный правильный вариант, когда нужен ровно один элемент по известному значению.
Сравнение вариантов
Подходит для отчётов, обработок больших массивов, соединений с другими таблицами. Требует знания языка запросов, но работает быстрее всего.
Подходит для простого перебора элементов с отбором по владельцу, родителю или пометке удаления. Медленнее запроса на больших объёмах.
Подходит для поиска одного конкретного элемента. Возвращает ссылку или пустую ссылку, если элемент не найден.
Выборка запросом: базовый синтаксис и примеры
Запрос создаётся объектом Запрос, текст пишется на встроенном языке запросов. Минимальный пример выборки всех элементов справочника «Номенклатура»:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Номенклатура.Ссылка КАК Ссылка,
| Номенклатура.Код КАК Код,
| Номенклатура.Наименование КАК Наименование
|ИЗ
| Справочник.Номенклатура КАК Номенклатура
|ГДЕ
| НЕ Номенклатура.ПометкаУдаления";
РезультатЗапроса = Запрос.Выполнить();
Выборка = РезультатЗапроса.Выбрать();
Пока Выборка.Следующий() Цикл
Сообщить(Выборка.Наименование);
КонецЦикла;
Обратите внимание на конструкцию ГДЕ НЕ Номенклатура.ПометкаУдаления — она исключает помеченные на удаление элементы. Это одна из самых частых ошибок новичков: без такого условия в отчёты и обработки попадают «мёртвые» записи, и итоги расходятся с данными, которые видит пользователь в интерфейсе.
Результат запроса можно обходить двумя способами: методом Выбрать() — последовательный перебор строк, и методом Выгрузить() — получение таблицы значений целиком. Таблица значений удобна, когда нужен произвольный доступ к строкам, сортировка или поиск по уже полученным данным, но занимает больше памяти.
Выборка с условиями: параметры и отборы
Условия отбора задаются в секции ГДЕ, а значения передаются через параметры — это защищает от ошибок конкатенации строк и ускоряет выполнение, так как СУБД может повторно использовать план запроса:
Запрос.Текст =
"ВЫБРАТЬ
| Товары.Ссылка КАК Ссылка,
| Товары.Наименование КАК Наименование
|ИЗ
| Справочник.Номенклатура КАК Товары
|ГДЕ
| Товары.Родитель = &Группа
| И Товары.Наименование ПОДОБНО &Маска
| И НЕ Товары.ПометкаУдаления";
Запрос.УстановитьПараметр("Группа", ГруппаТоваров);
Запрос.УстановитьПараметр("Маска", "%" + СтрокаПоиска + "%");
Оператор ПОДОБНО работает как поиск по шаблону: символ % означает любую последовательность символов. Для отбора по списку значений используйте конструкцию В (&СписокЗначений), передав в параметр массив или список значений. Для отбора по иерархии (элемент находится в группе или в любой её подгруппе) применяется оператор В ИЕРАРХИИ(&Группа).
Для сравнения с пустой ссылкой используйте конструкцию ЗНАЧЕНИЕ(Справочник.Номенклатура.ПустаяСсылка). Прямое сравнение с Неопределено или пустой строкой не сработает — типы не совпадут, и условие просто не отберёт ни одной записи.
Выборка методом Выбрать(): отбор по владельцу и родителю
Метод Выбрать() менеджера справочника возвращает объект выборки, который перебирается в цикле. Сигнатура метода: Выбрать(Родитель, Владелец, Отбор, Порядок) — все параметры необязательные. Пример перебора элементов, подчинённых конкретному владельцу:
Выборка = Справочники.ЕдиницыИзмерения.Выбрать(, НоменклатураСсылка);
Пока Выборка.Следующий() Цикл
Если Выборка.ПометкаУдаления Тогда
Продолжить;
КонецЕсли;
Сообщить(Выборка.Наименование);
КонецЦикла;
Третий параметр — структура отбора по реквизитам, для которых в конфигураторе включена индексация. Если попытаться отобрать по неиндексированному реквизиту, платформа выдаст ошибку. Четвёртый параметр задаёт порядок обхода, например "Наименование" для сортировки по алфавиту.
Для иерархических справочников есть метод ВыбратьИерархически() — он обходит элементы с учётом дерева групп. Учтите: в выборку попадают и группы, и элементы, поэтому внутри цикла обычно проверяют Если Выборка.ЭтоГруппа Тогда Продолжить; КонецЕсли;.
Поиск одного элемента: НайтиПоКоду, НайтиПоНаименованию, НайтиПоРеквизиту
Когда нужен конкретный элемент, перебирать всю выборку неэффективно. Платформа предоставляет методы точечного поиска, которые используют индексы и работают быстро даже на больших справочниках:
// Поиск по коду (второй параметр — искать по полному коду с учётом подчинения)
НайденныйЭлемент = Справочники.Номенклатура.НайтиПоКоду("00-000123");
// Поиск по наименованию (третий параметр — точное соответствие)
НайденныйЭлемент = Справочники.Контрагенты.НайтиПоНаименованию("ООО Ромашка", Истина);
// Поиск по значению реквизита (реквизит должен быть проиндексирован)
НайденныйЭлемент = Справочники.Контрагенты.НайтиПоРеквизиту("ИНН", "7701234567");
Если НайденныйЭлемент.Пустая() Тогда
Сообщить("Элемент не найден");
КонецЕсли;
Все три метода возвращают ссылку. Если элемент не найден, возвращается пустая ссылка — её обязательно проверяют методом Пустая() перед использованием, иначе при обращении к реквизитам получите ошибку или некорректные данные. По умолчанию методы не находят помеченные на удаление элементы, но у НайтиПоНаименованию() и НайтиПоКоду() есть параметры, позволяющие изменить это поведение — уточняйте сигнатуру в синтакс-помощнике для вашей версии платформы.
Выборка с учётом иерархии и подчинённых справочников
Иерархические справочники (например, «Номенклатура» с группами товаров) требуют отдельных приёмов. Чтобы получить все элементы конкретной группы включая вложенные подгруппы, в запросе используйте оператор В ИЕРАРХИИ:
Запрос.Текст =
"ВЫБРАТЬ
| Товары.Ссылка КАК Ссылка
|ИЗ
| Справочник.Номенклатура КАК Товары
|ГДЕ
| Товары.Ссылка В ИЕРАРХИИ(&Группа)
| И НЕ Товары.ЭтоГруппа";
Для подчинённых справочников (например, «Договоры контрагентов», подчинённые справочнику «Контрагенты») отбор строится по полю Владелец. В запросе это обычное условие ГДЕ Договоры.Владелец = &Контрагент, а в методе Выбрать() владелец передаётся вторым параметром. Попытка получить элементы подчинённого справочника без указания владельца вернёт данные по всем владельцам сразу — это частая причина лишних записей в обработках.
Как выбрать действие
Проверка результата и производительность
После выполнения запроса полезно проверить, вернул ли он данные: метод РезультатЗапроса.Пустой() возвращает Истина, если записей нет. Это позволяет корректно обработать ситуацию «ничего не найдено» вместо молчаливого пропуска цикла. Для отладки текста запроса используйте консоль запросов — она есть во многих типовых конфигурациях и доступна как внешняя обработка.
На производительность выборки больше всего влияют три фактора: наличие индексов по полям отбора, количество выбираемых полей и объём возвращаемых данных. Отбор по проиндексированному реквизиту выполняется быстро даже на миллионах записей; отбор по неиндексированному полю заставляет СУБД сканировать всю таблицу. Если реквизит часто используется в отборах, включите для него индексацию в конфигураторе — но не индексируйте всё подряд, так как каждый индекс замедляет запись.
В клиент-серверном варианте избегайте выборки в цикле с обращением к реквизитам через точку от ссылки: каждое такое обращение — отдельный запрос к базе. Вместо этого выбирайте все нужные поля сразу в исходном запросе. Правило «один запрос вместо тысячи мелких» — главный принцип быстрой работы с данными в 1С.
Как проверить результат
Совпадает с количеством элементов, видимых в списке справочника с теми же отборами
Записей больше — вероятно, не исключены помеченные на удаление или не задан отбор по владельцу
Поля заполнены ожидаемыми значениями, типы соответствуют реквизитам
Пустые значения там, где данные есть — возможно, выбрано не то поле или не хватает соединения
Метод Пустая() возвращает Ложь, реквизиты доступны
Возвращена пустая ссылка — проверьте формат кода и учёт подчинения
Часто задаваемые вопросы
Чем выборка запросом отличается от метода Выбрать()?
Запрос выполняется целиком на стороне СУБД и возвращает только нужные поля и записи — это быстрее и позволяет соединять таблицы. Метод Выбрать() перебирает элементы на стороне приложения и удобен для простых сценариев, но на больших объёмах работает медленнее и не умеет группировки и итоги.
Как выбрать только непомеченные на удаление элементы?
В запросе добавьте условие ГДЕ НЕ Справочник.ПометкаУдаления. При использовании метода Выбрать() проверяйте Выборка.ПометкаУдаления внутри цикла и пропускайте такие элементы оператором Продолжить.
Почему НайтиПоРеквизиту() выдаёт ошибку?
Метод работает только с реквизитами, для которых в конфигураторе включена индексация (свойство «Индексировать»). Проверьте настройки реквизита в конфигураторе либо замените поиск запросом с условием по этому реквизиту.
Как выбрать элементы справочника за определённый период?
Справочники не имеют периодичности сами по себе. Если нужна история изменений, данные хранятся в регистрах сведений. Отбор возможен по дате создания элемента только если в конфигурации есть соответствующий реквизит типа «Дата» — тогда используйте условие ГДЕ Реквизит МЕЖДУ &Начало И &Конец.
Можно ли отсортировать результат выборки?
Да. В запросе используйте секцию УПОРЯДОЧИТЬ ПО Наименование (или по нескольким полям через запятую, с ключевым словом УБЫВ для обратного порядка). В методе Выбрать() порядок задаётся четвёртым параметром, например Выбрать(,,, "Наименование").
Как получить данные, если наименования элементов дублируются?
Наименование не является уникальным полем, поэтому поиск по нему ненадёжен. Используйте уникальные идентификаторы: код (если контролируется уникальность), проиндексированный реквизит вроде ИНН или артикула, либо ссылку, полученную ранее из документа или другого объекта.
Что важно запомнить
Для выборки из справочника в 1С используйте запрос с параметрами и условием ГДЕ — это самый быстрый и гибкий способ. Для поиска одного элемента применяйте НайтиПоКоду(), НайтиПоНаименованию() или НайтиПоРеквизиту() с обязательной проверкой результата методом Пустая(). Всегда исключайте помеченные на удаление элементы, выбирайте только нужные поля и тестируйте массовые операции на копии базы.