К статье
Практический материал

Разработка и Конфигурация · 12 мин

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

Как сделать выборку из справочника в 1С: запрос с условиями, методы Выбрать() и НайтиПоКоду(), отбор по владельцу, обход иерархии, типичные ошибки и примеры кода.

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

Правильный выбор способа зависит от задачи. Если нужно получить тысячи элементов для отчёта — используйте запрос. Если нужно найти один элемент по коду или наименованию и изменить его — подойдут методы НайтиПоКоду() или НайтиПоНаименованию(). Ниже разобраны оба подхода с рабочими примерами кода, условиями отбора и типичными ошибками.

Какие способы выборки существуют и когда какой применять

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

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

Сравнение вариантов

Запрос (ВЫБРАТЬ ... ИЗ)

Подходит для отчётов, обработок больших массивов, соединений с другими таблицами. Требует знания языка запросов, но работает быстрее всего.

Метод Выбрать()

Подходит для простого перебора элементов с отбором по владельцу, родителю или пометке удаления. Медленнее запроса на больших объёмах.

НайтиПоКоду() / НайтиПоНаименованию()

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

Выборка запросом: базовый синтаксис и примеры

Запрос создаётся объектом Запрос, текст пишется на встроенном языке запросов. Минимальный пример выборки всех элементов справочника «Номенклатура»:

Запрос = Новый Запрос;

Запрос.Текст =

"ВЫБРАТЬ

| Номенклатура.Ссылка КАК Ссылка,

| Номенклатура.Код КАК Код,

| Номенклатура.Наименование КАК Наименование

|ИЗ

| Справочник.Номенклатура КАК Номенклатура

|ГДЕ

| НЕ Номенклатура.ПометкаУдаления";

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

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

Пока Выборка.Следующий() Цикл

Сообщить(Выборка.Наименование);

КонецЦикла;

Обратите внимание на конструкцию ГДЕ НЕ Номенклатура.ПометкаУдаления — она исключает помеченные на удаление элементы. Это одна из самых частых ошибок новичков: без такого условия в отчёты и обработки попадают «мёртвые» записи, и итоги расходятся с данными, которые видит пользователь в интерфейсе.

Результат запроса можно обходить двумя способами: методом Выбрать() — последовательный перебор строк, и методом Выгрузить() — получение таблицы значений целиком. Таблица значений удобна, когда нужен произвольный доступ к строкам, сортировка или поиск по уже полученным данным, но занимает больше памяти.

Выборка с условиями: параметры и отборы

Условия отбора задаются в секции ГДЕ, а значения передаются через параметры — это защищает от ошибок конкатенации строк и ускоряет выполнение, так как СУБД может повторно использовать план запроса:

Запрос.Текст =

"ВЫБРАТЬ

| Товары.Ссылка КАК Ссылка,

| Товары.Наименование КАК Наименование

|ИЗ

| Справочник.Номенклатура КАК Товары

|ГДЕ

| Товары.Родитель = &Группа

| И Товары.Наименование ПОДОБНО &Маска

| И НЕ Товары.ПометкаУдаления";

Запрос.УстановитьПараметр("Группа", ГруппаТоваров);

Запрос.УстановитьПараметр("Маска", "%" + СтрокаПоиска + "%");

Оператор ПОДОБНО работает как поиск по шаблону: символ % означает любую последовательность символов. Для отбора по списку значений используйте конструкцию В (&СписокЗначений), передав в параметр массив или список значений. Для отбора по иерархии (элемент находится в группе или в любой её подгруппе) применяется оператор В ИЕРАРХИИ(&Группа).

Для сравнения с пустой ссылкой используйте конструкцию ЗНАЧЕНИЕ(Справочник.Номенклатура.ПустаяСсылка). Прямое сравнение с Неопределено или пустой строкой не сработает — типы не совпадут, и условие просто не отберёт ни одной записи.

Типичные ошибки
01
Подстановка значений прямо в текст запроса через конкатенацию строк вместо параметров — риск ошибок синтаксиса и проблем с производительностью.
02
Отсутствие отбора по ПометкаУдаления — в результаты попадают удалённые элементы.
03
Сравнение ссылки со строкой или числом — условие молча не срабатывает, потому что типы не совпадают.
04
Поиск по наименованию без учёта того, что наименования не уникальны — находится не тот элемент.

Выборка методом Выбрать(): отбор по владельцу и родителю

Метод Выбрать() менеджера справочника возвращает объект выборки, который перебирается в цикле. Сигнатура метода: Выбрать(Родитель, Владелец, Отбор, Порядок) — все параметры необязательные. Пример перебора элементов, подчинённых конкретному владельцу:

Выборка = Справочники.ЕдиницыИзмерения.Выбрать(, НоменклатураСсылка);

Пока Выборка.Следующий() Цикл

Если Выборка.ПометкаУдаления Тогда

Продолжить;

КонецЕсли;

Сообщить(Выборка.Наименование);

КонецЦикла;

Третий параметр — структура отбора по реквизитам, для которых в конфигураторе включена индексация. Если попытаться отобрать по неиндексированному реквизиту, платформа выдаст ошибку. Четвёртый параметр задаёт порядок обхода, например "Наименование" для сортировки по алфавиту.

Для иерархических справочников есть метод ВыбратьИерархически() — он обходит элементы с учётом дерева групп. Учтите: в выборку попадают и группы, и элементы, поэтому внутри цикла обычно проверяют Если Выборка.ЭтоГруппа Тогда Продолжить; КонецЕсли;.

Поиск одного элемента: НайтиПоКоду, НайтиПоНаименованию, НайтиПоРеквизиту

Когда нужен конкретный элемент, перебирать всю выборку неэффективно. Платформа предоставляет методы точечного поиска, которые используют индексы и работают быстро даже на больших справочниках:

// Поиск по коду (второй параметр — искать по полному коду с учётом подчинения)

НайденныйЭлемент = Справочники.Номенклатура.НайтиПоКоду("00-000123");

// Поиск по наименованию (третий параметр — точное соответствие)

НайденныйЭлемент = Справочники.Контрагенты.НайтиПоНаименованию("ООО Ромашка", Истина);

// Поиск по значению реквизита (реквизит должен быть проиндексирован)

НайденныйЭлемент = Справочники.Контрагенты.НайтиПоРеквизиту("ИНН", "7701234567");

Если НайденныйЭлемент.Пустая() Тогда

Сообщить("Элемент не найден");

КонецЕсли;

Все три метода возвращают ссылку. Если элемент не найден, возвращается пустая ссылка — её обязательно проверяют методом Пустая() перед использованием, иначе при обращении к реквизитам получите ошибку или некорректные данные. По умолчанию методы не находят помеченные на удаление элементы, но у НайтиПоНаименованию() и НайтиПоКоду() есть параметры, позволяющие изменить это поведение — уточняйте сигнатуру в синтакс-помощнике для вашей версии платформы.

Выборка с учётом иерархии и подчинённых справочников

Иерархические справочники (например, «Номенклатура» с группами товаров) требуют отдельных приёмов. Чтобы получить все элементы конкретной группы включая вложенные подгруппы, в запросе используйте оператор В ИЕРАРХИИ:

Запрос.Текст =

"ВЫБРАТЬ

| Товары.Ссылка КАК Ссылка

|ИЗ

| Справочник.Номенклатура КАК Товары

|ГДЕ

| Товары.Ссылка В ИЕРАРХИИ(&Группа)

| И НЕ Товары.ЭтоГруппа";

Для подчинённых справочников (например, «Договоры контрагентов», подчинённые справочнику «Контрагенты») отбор строится по полю Владелец. В запросе это обычное условие ГДЕ Договоры.Владелец = &Контрагент, а в методе Выбрать() владелец передаётся вторым параметром. Попытка получить элементы подчинённого справочника без указания владельца вернёт данные по всем владельцам сразу — это частая причина лишних записей в обработках.

Маршрут решения

Как выбрать действие

Нужен один элемент по известному коду, ИНН или наименованиюИспользуйте НайтиПоКоду(), НайтиПоРеквизиту() или НайтиПоНаименованию() и проверьте результат методом Пустая().
Нужны все элементы группы включая подгруппыИспользуйте запрос с условием Ссылка В ИЕРАРХИИ(&Группа).
Нужно перебрать элементы подчинённого справочника одного владельцаИспользуйте Выбрать(, Владелец) или запрос с условием по полю Владелец.
Нужны данные для отчёта или выгрузки большого объёмаИспользуйте запрос с выбором только нужных полей и обработкой результата через Выбрать() или Выгрузить().

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

После выполнения запроса полезно проверить, вернул ли он данные: метод РезультатЗапроса.Пустой() возвращает Истина, если записей нет. Это позволяет корректно обработать ситуацию «ничего не найдено» вместо молчаливого пропуска цикла. Для отладки текста запроса используйте консоль запросов — она есть во многих типовых конфигурациях и доступна как внешняя обработка.

На производительность выборки больше всего влияют три фактора: наличие индексов по полям отбора, количество выбираемых полей и объём возвращаемых данных. Отбор по проиндексированному реквизиту выполняется быстро даже на миллионах записей; отбор по неиндексированному полю заставляет СУБД сканировать всю таблицу. Если реквизит часто используется в отборах, включите для него индексацию в конфигураторе — но не индексируйте всё подряд, так как каждый индекс замедляет запись.

В клиент-серверном варианте избегайте выборки в цикле с обращением к реквизитам через точку от ссылки: каждое такое обращение — отдельный запрос к базе. Вместо этого выбирайте все нужные поля сразу в исходном запросе. Правило «один запрос вместо тысячи мелких» — главный принцип быстрой работы с данными в 1С.

Контрольные точки

Как проверить результат

Количество записей в выборке
Норма

Совпадает с количеством элементов, видимых в списке справочника с теми же отборами

Тревожный признак

Записей больше — вероятно, не исключены помеченные на удаление или не задан отбор по владельцу

Содержимое полей
Норма

Поля заполнены ожидаемыми значениями, типы соответствуют реквизитам

Тревожный признак

Пустые значения там, где данные есть — возможно, выбрано не то поле или не хватает соединения

Элемент найден методом НайтиПоКоду()
Норма

Метод Пустая() возвращает Ложь, реквизиты доступны

Тревожный признак

Возвращена пустая ссылка — проверьте формат кода и учёт подчинения

Часто задаваемые вопросы

Чем выборка запросом отличается от метода Выбрать()?

Запрос выполняется целиком на стороне СУБД и возвращает только нужные поля и записи — это быстрее и позволяет соединять таблицы. Метод Выбрать() перебирает элементы на стороне приложения и удобен для простых сценариев, но на больших объёмах работает медленнее и не умеет группировки и итоги.

Как выбрать только непомеченные на удаление элементы?

В запросе добавьте условие ГДЕ НЕ Справочник.ПометкаУдаления. При использовании метода Выбрать() проверяйте Выборка.ПометкаУдаления внутри цикла и пропускайте такие элементы оператором Продолжить.

Почему НайтиПоРеквизиту() выдаёт ошибку?

Метод работает только с реквизитами, для которых в конфигураторе включена индексация (свойство «Индексировать»). Проверьте настройки реквизита в конфигураторе либо замените поиск запросом с условием по этому реквизиту.

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

Справочники не имеют периодичности сами по себе. Если нужна история изменений, данные хранятся в регистрах сведений. Отбор возможен по дате создания элемента только если в конфигурации есть соответствующий реквизит типа «Дата» — тогда используйте условие ГДЕ Реквизит МЕЖДУ &Начало И &Конец.

Можно ли отсортировать результат выборки?

Да. В запросе используйте секцию УПОРЯДОЧИТЬ ПО Наименование (или по нескольким полям через запятую, с ключевым словом УБЫВ для обратного порядка). В методе Выбрать() порядок задаётся четвёртым параметром, например Выбрать(,,, "Наименование").

Как получить данные, если наименования элементов дублируются?

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

Итог

Что важно запомнить

Для выборки из справочника в 1С используйте запрос с параметрами и условием ГДЕ — это самый быстрый и гибкий способ. Для поиска одного элемента применяйте НайтиПоКоду(), НайтиПоНаименованию() или НайтиПоРеквизиту() с обязательной проверкой результата методом Пустая(). Всегда исключайте помеченные на удаление элементы, выбирайте только нужные поля и тестируйте массовые операции на копии базы.