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

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

Объект «Запрос» во встроенном языке 1С: назначение и практика применения

Для чего предназначен объект Запрос встроенного языка 1С: выборка данных, параметры, пакеты запросов, временные таблицы, примеры кода и типичные ошибки разработчиков.

Объект «Запрос» — основной инструмент встроенного языка 1С для чтения данных из информационной базы. Через него разработчик обращается к таблицам справочников, документов, регистров накопления и сведений на языке запросов, близком к SQL, и получает результат в виде выборки, таблицы значений или дерева. Без этого объекта невозможно построить ни один отчёт, обработку или сложную бизнес-логику, опирающуюся на данные базы.

Главное преимущество объекта «Запрос» перед перебором объектов через методы «Выбрать()» — скорость и декларативность. Запрос выполняется на стороне сервера СУБД, выбирает только нужные поля и строки, а разработчик описывает желаемый результат, а не пошаговый алгоритм обхода данных. Это снижает нагрузку на сеть и сервер приложений, особенно в клиент-серверных базах с большим объёмом информации.

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

Что такое объект «Запрос» и какую задачу он решает

Объект «Запрос» создаётся конструктором Новый Запрос или Новый Запрос("текст запроса"). Он представляет собой программную обёртку над текстом на языке запросов 1С: разработчик задаёт текст, передаёт параметры, выполняет запрос и обрабатывает результат. Сам по себе объект не хранит данные — он лишь описывает, какие данные нужны и как их получить.

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

Важно понимать границу: объект «Запрос» предназначен только для чтения данных. Изменение записей выполняется другими средствами — через объектные методы («Записать()» у объектов и наборов записей). Попытки «обновить данные запросом» — признак непонимания архитектуры платформы.

Базовый цикл работы: от создания до выборки

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

Порядок работы с объектом «Запрос»
  1. 1
    Создайте объект: Запрос = Новый Запрос
  2. 2
    Заполните свойство «Текст» текстом на языке запросов
  3. 3
    Установите параметры через Запрос.УстановитьПараметр(Имя, Значение)
  4. 4
    Выполните запрос: Результат = Запрос.Выполнить()
  5. 5
    Получите выборку: Выборка = Результат.Выбрать() — и обойдите её в цикле Пока Выборка.Следующий()
  6. 6
    Проверьте результат на пустоту через Результат.Пустой() до начала обхода

Пример минимального кода выборки номенклатуры по виду:

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

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

"ВЫБРАТЬ

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

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

|ИЗ

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

|ГДЕ

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

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

Если Результат.Пустой() Тогда

Возврат;

КонецЕсли;

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

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

// обработка строки

КонецЦикла;

Проверка Результат.Пустой() перед обходом — хорошая привычка: она позволяет заранее обработать ситуацию отсутствия данных и не выполнять лишнюю работу. Если нужна вся таблица целиком, например для передачи в табличное поле или построения отчёта, используйте Результат.Выгрузить(), который вернёт таблицу значений, или Результат.Выгрузить(ОбходРезультатаЗапроса.ПоГруппировкамСИерархией) для дерева.

Параметры запроса: защита от ошибок и неявных преобразований

Параметры передаются в текст запроса через символ «&» и устанавливаются методом УстановитьПараметр(). Параметризация обязательна почти всегда: она отделяет данные от текста запроса, упрощает повторное выполнение с другими значениями и защищает от ошибок форматирования строк и дат.

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

"ВЫБРАТЬ

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

| СУММА(Продажи.Количество) КАК Количество

|ИЗ

| РегистрНакопления.Продажи.Обороты(&НачалоПериода, &КонецПериода, , ) КАК Продажи

|СГРУППИРОВАТЬ ПО

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

Запрос.УстановитьПараметр("НачалоПериода", НачалоМесяца(ТекущаяДатаСеанса()));

Запрос.УстановитьПараметр("КонецПериода", КонецМесяца(ТекущаяДатаСеанса()));

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

Отдельный случай — передача списка значений или массива в условие «В (&Список)». Платформа корректно разворачивает массивы и списки значений в параметры-списки, но таблицу значений напрямую в параметр условия передать нельзя — её помещают во временную таблицу через пакетный запрос.

Пакетные запросы и временные таблицы

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

Временные таблицы живут в менеджере временных таблиц (объект «МенеджерВременныхТаблиц»). Если менеджер назначен запросу через свойство МенеджерВременныхТаблиц, созданные им таблицы доступны последующим запросам, использующим тот же менеджер. Это стандартный приём для сложных отчётов и проведения документов.

Индексирование временных таблиц через конструкцию «ИНДЕКСИРОВАТЬ ПО» заметно ускоряет соединения на больших объёмах. Если временная таблица содержит тысячи строк и участвует в соединении, отсутствие индекса по полю связи — типичная причина медленного выполнения.

Способы обхода результата: выборка, таблица, дерево

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

Способы получения результата

Выборка (Выбрать)

Построчный обход больших выборок, минимальный расход памяти; нельзя вернуться к предыдущим строкам

Таблица значений (Выгрузить)

Сортировка, поиск, свёртка, передача в форму; весь результат загружается в память

Дерево (Выгрузить с обходом по группировкам)

Иерархические отчёты и группировки; требует ИТОГИ в тексте запроса

Выборка по группировкам

Обход итогов и детальных записей без выгрузки дерева; нужен контроль уровней через ТипЗаписи

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

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

Как проверить корректность работы запроса

Количество строк результата
Норма

Совпадает с ожиданием по тестовым данным

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

Строк больше из-за декартова произведения при неверном соединении

Параметры
Норма

Все параметры из текста установлены в коде

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

Ошибка «Параметр не найден» при выполнении

Время выполнения
Норма

Запрос отрабатывает быстро на рабочем объёме данных

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

Запрос в цикле или соединение без индекса — секунды на каждую итерацию

Пустой результат
Норма

Обработан веткой кода через Результат.Пустой()

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

Обращение к полям выборки без проверки приводит к пустым данными в отчёте

Типичные ошибки и ограничения

Самая дорогая по последствиям ошибка — выполнение запроса в цикле. Когда вместо одного запроса с соединением разработчик обходит выборку и для каждой строки выполняет новый запрос, нагрузка на СУБД растёт кратно. Правильное решение почти всегда — один запрос с соединением или временной таблицей.

Типичные ошибки при работе с объектом «Запрос»
01
Запрос в цикле вместо соединения таблиц — резкое падение производительности и нагрузка на СУБД
02
Выборка всех полей через «ВЫБРАТЬ *» — лишний трафик и неявное получение полей, которых нет в выборке при обращении к ним
03
Отсутствие проверки Результат.Пустой() — скрытые ошибки логики при отсутствии данных
04
Передача значений конкатенацией в текст — ошибки форматов дат и чисел, перекомпиляция плана запроса
05
Использование НЕ В с полем, допускающим NULL — неожиданно пустой результат из-за трёхзначной логики
06
Забытые временные таблицы без УНИЧТОЖИТЬ — рост потребления памяти в длительных операциях

Ещё одно ограничение: запрос работает в рамках прав доступа текущего пользователя (если не используется привилегированный режим) и виртуальных таблиц с их особенностями. Например, виртуальная таблица «Остатки» без указания периода строится на текущую дату сеанса — это часто становится источником «неправильных» остатков при тестировании.

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

Как выбрать подход

Нужно прочитать данные один раз и обработать построчноИспользуйте Выбрать() и обход выборки
Данные нужно сортировать, искать или передать в формуИспользуйте Выгрузить() в таблицу значений
Нужно передать в запрос таблицу значений или многоступенчатый расчётИспользуйте пакетный запрос с менеджером временных таблиц
Запрос выполняется внутри циклаОстановитесь и перепишите на один запрос с соединением или временной таблицей

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

Практическое правило: сначала отладьте текст запроса в консоли запросов на реальных данных, добейтесь корректного результата и приемлемого времени выполнения, и только потом переносите текст в модуль. Это избавляет от циклов «изменил код — запустил — проверил».

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

Итог

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

Объект «Запрос» предназначен для чтения данных из базы на языке запросов: задайте текст, установите параметры, выполните и обработайте результат подходящим способом. Избегайте запросов в цикле, используйте параметры вместо конкатенации, а для сложных расчётов — пакетные запросы с временными таблицами.

Частые вопросы

Чем объект «Запрос» отличается от системы компоновки данных (СКД)?

Объект «Запрос» — это программное выполнение одного текста запроса с фиксированным набором параметров. СКД — надстройка, которая позволяет пользователю менять отборы, группировки и поля отчёта без изменения кода. Для отчётов с настраиваемой структурой используют СКД, для служебных выборок в алгоритмах — объект «Запрос».

Можно ли изменять данные базы через объект «Запрос»?

Нет. Язык запросов 1С не содержит операторов INSERT, UPDATE или DELETE. Изменение данных выполняется через объектную модель: методы «Записать()» у объектов справочников, документов и наборов записей регистров. Запрос только читает.

Почему запрос с условием «НЕ В» возвращает пустой результат?

Если поле в условии «НЕ В» или в списке значений может содержать NULL, срабатывает трёхзначная логика: сравнение с NULL даёт неопределённость, и строка отбрасывается. Исключите NULL через ЕСТЬNULL или добавьте условие «ИЛИ Поле ЕСТЬ NULL».

Как передать таблицу значений в запрос?

Напрямую в условие — никак. Приём такой: передайте таблицу как параметр и в первом запросе пакета выполните «ВЫБРАТЬ ... ПОМЕСТИТЬ ВТ ИЗ &Таблица», затем соединяйтесь с временной таблицей в основном запросе. После работы уничтожьте её оператором УНИЧТОЖИТЬ.

Что быстрее: обход выборки или выгрузка в таблицу значений?

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

Нужно ли создавать новый объект «Запрос» для каждого выполнения?

Не обязательно: один объект можно выполнять повторно, меняя параметры. Но если меняется текст запроса или менеджер временных таблиц, проще создать новый объект — это делает код прозрачнее и исключает влияние прежнего состояния.