Вывод результата запроса в 1С: от конструктора до кода

· 9 мин

Содержание

Чтобы вывести запрос в 1С, нужно два действия: составить текст запроса и выполнить его в коде. Текст пишут руками или собирают в конструкторе запроса (вызывается из модуля правой кнопкой мыши), а выполнение сводится к трём строкам — создать объект Запрос, задать Текст и вызвать Выполнить().

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

Какими способами выполняют запрос в 1С

Запрос в 1С — это чтение данных из базы на языке, похожем на SQL. Вывести его результат можно четырьмя путями, и выбор зависит от задачи:

  • 🧱 Конструктор запроса — визуальная сборка текста мышью, без знания синтаксиса. Подходит новичкам и для сложных соединений.
  • ⌨️ Программный вызов в модуле — объект Запрос, обход Выборки в цикле. Основной способ в обработках и обработчиках документов.
  • 📊 Выгрузка в таблицу значений — результат целиком попадает в ТаблицаЗначений, дальше с ним работают как с массивом строк.
  • 📄 Отчёт или форма — вывод на экран через систему компоновки данных (СКД) или табличный документ.

Внутри любого из этих путей текст запроса одинаков. Меняется только то, как вы получаете и показываете результат. Разберём по порядку.

Как собрать запрос через конструктор запроса

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

Порядок вызова в Конфигураторе или в режиме расширения:

  1. Откройте модуль (общий модуль, модуль обработки, модуль формы).
  2. Поставьте курсор внутрь пустой строки, где будет текст запроса.
  3. Нажмите правую кнопку мыши → Конструктор запроса.... Если в строке ещё нет текста, 1С предложит создать новый запрос.

Откроется окно с вкладками. Основные:

  • Таблицы и поля — слева список таблиц конфигурации, перетаскиваете нужные в среднюю колонку, из них поля — в правую.
  • Связи — соединения между таблицами (левое, внутреннее), если таблиц больше одной.
  • Условия — отбор (аналог ГДЕ), сюда же задаются параметры.
  • Группировка — суммы, количества, группировочные поля.
  • Порядок — сортировка результата.
  • Объединения/Псевдонимы — имена колонок результата.

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

После ОК конструктор вставит в модуль готовый текст в кавычках с разделителями строк |. Его можно дальше править руками — повторный вызов конструктора на существующем тексте откроет его же для редактирования.

Программный вывод запроса: синтаксис и пример кода

Минимальный рабочий запрос в коде выглядит так:

Запрос = Новый Запрос;
Запрос.Текст =
    "ВЫБРАТЬ
    |   Номенклатура.Ссылка КАК Номенклатура,
    |   Номенклатура.Код КАК Код,
    |   Номенклатура.Артикул КАК Артикул
    |ИЗ
    |   Справочник.Номенклатура КАК Номенклатура
    |ГДЕ
    |   НЕ Номенклатура.ПометкаУдаления
    |УПОРЯДОЧИТЬ ПО
    |   Номенклатура.Наименование";

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

Пока Выборка.Следующий() Цикл
    Сообщить(СтрШаблон("%1 — %2", Выборка.Код, Выборка.Артикул));
КонецЦикла;

Что здесь происходит по шагам:

  1. Новый Запрос — создаём объект запроса.
  2. Запрос.Текст — присваиваем текст. Символ | в начале строки — служебный разделитель многострочного текста, его ставит сам конструктор.
  3. Выполнить() возвращает объект РезультатЗапроса.
  4. Выбрать() даёт ВыборкуИзРезультатаЗапроса — курсор, который Следующий() двигает по строкам.
  5. Внутри цикла поля читаются через точку: Выборка.Код, Выборка.Артикул.

Поля в цикле доступны ровно под теми именами, которые заданы псевдонимами после КАК в запросе. Если написали Номенклатура.Код КАК Код, обращение будет Выборка.Код. Напишете Выборка.Код1 — получите ошибку на этапе выполнения.

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

Запрос.Текст =
    "ВЫБРАТЬ
    |   Продажи.Номенклатура КАК Номенклатура,
    |   Продажи.Количество КАК Количество
    |ИЗ
    |   РегистрНакопления.Продажи КАК Продажи
    |ГДЕ
    |   Продажи.Период МЕЖДУ &ДатаНачала И &ДатаКонца";

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

Имя параметра в тексте начинается с &, а в коде пишется без него. На сервере текущую дату берут через ТекущаяДатаСеанса() — это корректный серверный вызов.

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

Когда результат нужен не для построчного вывода, а для дальнейшей обработки — проще выгрузить его целиком в таблицу значений:

ТаблицаНоменклатуры = Запрос.Выполнить().Выгрузить();

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

Для Каждой Строка Из ТаблицаНоменклатуры Цикл
    Сообщить(Строка.Код);
КонецЦикла;

// количество строк, поиск, выгрузка в массив
Количество = ТаблицаНоменклатуры.Количество();
Найденные  = ТаблицаНоменклатуры.НайтиСтроки(Новый Структура("Артикул", "АБ-100"));

Разница между Выбрать() и Выгрузить():

СпособЧто возвращаетКогда применять
Выбрать()Курсор, перебор в циклеДанных много, нужна только обработка по одной строке
Выгрузить()Таблицу значений целиком в памятьНужны сортировка, поиск, передача таблицы в другую функцию, вывод на форму

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

Чтобы показать таблицу значений пользователю, положите её в реквизит формы типа ТаблицаЗначений и выведите на форму элементом «Таблица». Данные появятся в табличном виде прямо в окне обработки.

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

Когда одного ВЫБРАТЬ мало — результат одного запроса нужен как источник для следующего — применяют временные таблицы и пакеты.

Временная таблица создаётся конструкцией ПОМЕСТИТЬ и живёт, пока существует менеджер временных таблиц:

Запрос = Новый Запрос;
Запрос.МенеджерВременныхТаблиц = Новый МенеджерВременныхТаблиц;

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

Запрос.Выполнить();

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

Пакетный запрос — несколько запросов в одном тексте, разделённых точкой с запятой. Выполняются за один проход:

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

МассивРезультатов = Запрос.ВыполнитьПакет();
ПоследнийРезультат = МассивРезультатов[МассивРезультатов.ВГраница()];

ВыполнитьПакет() возвращает массив результатов — по одному на каждый запрос пакета. Элемент берут по индексу; ВГраница() даёт индекс последнего. Если нужны сами временные таблицы как таблицы значений, используют ВыполнитьПакетСВременнымиТаблицами().

Пакеты удобнее череды отдельных Выполнить(): меньше обращений к базе и наглядная последовательность шагов в одном тексте.

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

Построчный Сообщить() годится для отладки. Для готового результата на экране есть более опрятные варианты.

  • 📈 Система компоновки данных (СКД) — штатный механизм отчётов. Создаёте объект Отчёт или внешний отчёт, в схеме компоновки задаёте тот же запрос, а вывод в табличный документ, диаграмму и группировки СКД собирает сама. Пользователь получает настраиваемый отчёт с отборами и итогами.
  • 🧰 Внешняя обработка — текст запроса в модуле, результат выгружаете в таблицу значений и показываете на форме элементом «Таблица». Быстрый способ сделать разовую выборку без публикации отчёта.
  • 📋 Табличный документ — если нужен печатный вид, результат выводят в ТабличныйДокумент через макет. Применяют для печатных форм и выгрузок на печать.

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

Для печатной формы результат выводят в ТабличныйДокумент: берут макет с именованными областями, заполняют область параметрами из строки выборки и выводят её в цикле методом Вывести. Это механизм печати накладных, актов и прайс-листов.

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

Оптимизация и отладка запросов

Медленный запрос чаще всего лечится не железом, а текстом. Базовые правила:

  • Не обращайтесь к полям через точку от составных типов (Документ.Контрагент.Родитель) — платформа добавит лишние соединения. Вынесите нужное во временную таблицу.
  • Для остатков и оборотов регистров берите виртуальные таблицы (Остатки, Обороты), а не считайте сумму по таблице движений вручную.
  • Избегайте ИЛИ в условиях соединения — это тормозит выборку. Разбейте на ОБЪЕДИНИТЬ ВСЕ.
  • Большие временные таблицы индексируйте через ИНДЕКСИРОВАТЬ ПО.
  • Не тащите в результат поля, которые не используете.
  • Если нужна только часть строк, ограничивайте выборку через ВЫБРАТЬ ПЕРВЫЕ N — платформа не станет читать всю таблицу.
  • Соединение больших таблиц делайте через заранее отобранную временную таблицу, а не напрямую с полной таблицей движений.

Для отладки и проверки результата пригодятся:

  1. Консоль запросов — внешняя обработка, в которой пишут текст запроса, задают параметры и сразу видят результат таблицей, без правки кода конфигурации. Классический инструмент разработчика; поставляется отдельной обработкой.
  2. Отладчик платформы — поставьте точку останова после Выполнить() и посмотрите результат через выгрузку в таблицу значений в окне просмотра значения.
  3. Замер производительности — в отладчике запускает подсчёт времени по строкам кода, показывает, сколько заняло именно выполнение запроса.
  4. План запроса — для серверной базы медленные запросы смотрят средствами СУБД (например, план выполнения на стороне PostgreSQL или MS SQL).

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

Проверка перед запуском запроса
Выполнено: 0 / 5

Частые ошибки при выводе запроса

Ошибки при выводе запроса почти всегда однотипны и ловятся до запуска.

  • ❌ Обращение к полю, которого нет в выборке. Выборка.Количество падает, если в тексте нет поля с псевдонимом Количество. Проверьте имена после КАК.
  • ❌ Параметр не установлен. В тексте есть &ДатаНачала, а УстановитьПараметр для него не вызван — запрос вернёт пусто или ошибку. Устанавливайте все параметры из текста.
  • ❌ Склейка значения в текст запроса. "ГДЕ Код = " + Код — так делать нельзя: ломается на спецсимволах и небезопасно. Всегда через параметр &Код.
  • ❌ Пустая проверка результата. Перед обходом полезно проверить Если Результат.Пустой() Тогда ... КонецЕсли;, иначе цикл просто не отработает молча.
  • ❌ Потерянный менеджер временных таблиц. Второй запрос не видит ВремТовары, если МенеджерВременныхТаблиц не назначен обоим запросам (или создан заново).

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

Чем отличается `Выбрать()` от `Выгрузить()`?
Выбрать() возвращает курсор для обхода результата в цикле по одной строке — экономит память. Выгрузить() отдаёт весь результат сразу в таблицу значений — удобно для поиска, сортировки и передачи дальше, но держит данные в памяти.
Как передать значение в запрос, чтобы не ломался синтаксис?
Только через параметр: в тексте &ИмяПараметра, в коде Запрос.УстановитьПараметр("ИмяПараметра", Значение). Склеивать значения в строку текста нельзя.
Можно ли в одном запросе получить сразу несколько результатов?
Да, это пакетный запрос: несколько ВЫБРАТЬ, разделённых ;. Выполняется методом ВыполнитьПакет(), который возвращает массив результатов — по одному на каждый запрос пакета.
Для чего нужны временные таблицы?
Чтобы результат одного запроса стал источником для следующего. Создаются через ПОМЕСТИТЬ ИмяТаблицы при назначенном МенеджерВременныхТаблиц. Крупные временные таблицы индексируют через ИНДЕКСИРОВАТЬ ПО для скорости соединений.
Как вывести результат запроса в готовый отчёт на экран?
Через систему компоновки данных: тот же текст запроса кладётся в схему компоновки, а шапку, группировки и итоги СКД строит сама. Для разовой выборки проще выгрузить результат в таблицу значений и показать на форме обработки.
Где быстро проверить запрос, не трогая код конфигурации?
В консоли запросов — внешней обработке, куда вставляют текст, задают параметры и сразу видят результат таблицей. Это стандартный инструмент разработчика для отладки выборок.