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