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

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

Как в 1С написать запрос: руководство для начинающих

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

Язык запросов 1С — основной инструмент получения данных из информационной базы. Он похож на SQL, но работает не с физическими таблицами базы, а с объектами конфигурации: справочниками, документами, регистрами. Чтобы написать рабочий запрос, достаточно понимать структуру конструкции ВЫБРАТЬ–ИЗ–ГДЕ и уметь пользоваться встроенным конструктором запросов.

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

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

Что нужно знать о языке запросов 1С перед началом

Язык запросов 1С — декларативный: вы описываете, какие данные нужны, а платформа сама решает, как их извлечь. Запрос только читает данные; изменить что-то в базе через запрос нельзя, для записи используются объекты (СправочникОбъект, ДокументОбъект и т.д.).

Имена таблиц в запросе — это имена объектов метаданных: Справочник.Номенклатура, Документ.РеализацияТоваровУслуг, РегистрНакопления.ТоварыНаСкладах. Внутри запроса используются русские ключевые слова (ВЫБРАТЬ, ИЗ, ГДЕ, СГРУППИРОВАТЬ ПО), но допускаются и английские аналоги (SELECT, FROM, WHERE).

Поле со звёздочкой (ВЫБРАТЬ *) работает, но в рабочем коде его лучше избегать: запрос вытащит все поля таблицы, включая ненужные, что замедлит выполнение и увеличит трафик между сервером 1С и СУБД.

Как написать первый запрос: минимальный пример

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

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

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

"ВЫБРАТЬ

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

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

|ИЗ

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

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

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

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

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

КонецЦикла;

Разберём ключевые элементы. Псевдоним таблицы (КАК Номенклатура после ИЗ) позволяет коротко ссылаться на поля. Псевдонимы полей (КАК Наименование) определяют имена колонок в результате — по ним вы обращаетесь к данным в цикле выборки.

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

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

Конструктор запроса избавляет от необходимости помнить синтаксис. Он вызывается из контекстного меню в модуле: правый клик внутри строки с текстом запроса → «Конструктор запроса». Если текста ещё нет, конструктор создаст заготовку.

Порядок работы в конструкторе: на закладке «Таблицы и поля» выберите источник (например, справочник Номенклатура), перенесите нужные поля в список выборки. На закладке «Условия» задайте отборы, на закладке «Группировка» — итоги, на закладке «Объединения/Псевдонимы» — имена полей результата. После нажатия «ОК» конструктор сформирует готовый текст.

Конструктор удобен и для изучения: соберите запрос мышкой, а потом посмотрите, какой текст он сгенерировал. Так быстрее запоминаются конструкции ЛЕВОЕ СОЕДИНЕНИЕ, СГРУППИРОВАТЬ ПО и обращения к виртуальным таблицам.

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

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

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

"ВЫБРАТЬ

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

| СУММА(Товары.Количество) КАК Количество

|ИЗ

| Документ.РеализацияТоваровУслуг.Товары КАК Товары

|ГДЕ

| Товары.Ссылка.Дата МЕЖДУ &НачалоПериода И &КонецПериода

| И Товары.Ссылка.Проведен

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

| Товары.Номенклатура";

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

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

Параметры задаются строго через УстановитьПараметр() до вызова Выполнить(). Если параметр объявлен в тексте, но не установлен — платформа выдаст ошибку «Переменная не определена». В параметры можно передавать ссылки, даты, числа, строки, массивы и списки значений (для условия В) и даже пустые ссылки.

Для отбора по списку значений используйте оператор В: ГДЕ Номенклатура В (&СписокНоменклатуры), а в параметр передайте массив или список значений. Это работает быстрее, чем цепочка условий ИЛИ.

Как соединять таблицы и работать с виртуальными таблицами

Соединения нужны, когда данные лежат в разных объектах: например, документ и регистр, справочник и регистр сведений с ценами. Чаще всего используется ЛЕВОЕ СОЕДИНЕНИЕ — оно сохраняет все строки левой таблицы, даже если справа совпадений нет.

ВЫБРАТЬ

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

Остатки.КоличествоОстаток КАК Остаток

ИЗ

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

ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ТоварыНаСкладах.Остатки(&Период, Склад = &Склад) КАК Остатки

ПО Номенклатура.Ссылка = Остатки.Номенклатура

Обратите внимание на синтаксис виртуальной таблицы Остатки(&Период, Склад = &Склад): первый параметр — период, на который считаются остатки, второй — условие отбора. Отбор внутри параметров виртуальной таблицы работает значительно быстрее, чем тот же отбор в секции ГДЕ, потому что платформа сначала сужает выборку, а потом соединяет.

Если при левом соединении совпадений не нашлось, поля правой таблицы вернут NULL. Для подстановки значения по умолчанию используйте ЕСТЬNULL: ЕСТЬNULL(Остатки.КоличествоОстаток, 0) КАК Остаток. Без этого арифметика с NULL даст NULL и испортит итоги.

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

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

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

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

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

Строк больше — вероятно дублирование из-за соединения; меньше — лишнее условие в ГДЕ

Суммы и остатки
Норма

Совпадают со штатным отчётом конфигурации по тем же данным

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

Расхождения — проверьте период виртуальной таблицы и отбор по проведённым документам

Поля из соединённой таблицы
Норма

Заполнены или заменены через ЕСТЬNULL

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

NULL там, где ожидалось число или строка

Где отлаживать запрос: консоль запросов

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

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

Консоль показывает и реальные значения параметров, что помогает найти классическую ошибку: параметр передан с неправильным типом (например, строка вместо ссылки) и условие ГДЕ молча ничего не отбирает.

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

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

Даже синтаксически верный запрос может работать плохо. Самая частая причина медленных запросов — обращение к полям через несколько точек и отбор по виртуальной таблице в секции ГДЕ вместо параметров. Вторая по частоте проблема — соединение по неиндексированным полям или по выражениям.

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

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

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

Чем запрос отличается от обхода данных через методы объектов?

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

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

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

Что такое временные таблицы и когда они нужны?

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

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

Чаще всего причина в параметрах: передан неверный тип (строка вместо ссылки), не та дата (например, без учёта времени — документы позже 00:00:00 отсекаются) или лишнее условие в ГДЕ. Проверьте запрос в консоли с теми же параметрами и поочерёдно убирайте условия, чтобы найти срабатывающее.

Можно ли в запросе получить данные за период с итогами по месяцам?

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

Где посмотреть синтаксис языка запросов в самой программе?

В конфигураторе есть встроенный синтакс-помощник: меню «Справка» → «Синтакс-помощник», раздел «Встроенный язык» → «Работа с запросами». Там описаны все конструкции языка запросов, агрегатные функции и работа с объектом Запрос. Это основной справочник, доступный без интернета.

Итог

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

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