В системе 1С:Предприятие работа с данными часто строится на основе языка запросов — мощного инструмента для извлечения, фильтрации и обработки информации из базы. Но даже опытные пользователи иногда сталкиваются с необходимостью сделать запрос более гибким, адаптивным или динамичным. Здесь на помощь приходят параметры запроса — специальные переменные, которые позволяют передавать значения в текст запроса извне, не изменяя его структуру.
Почему это важно? Представьте, что вам нужно получить список документов за разные периоды, фильтровать товары по разным категориям или искать контрагентов по частичному совпадению названия. Без параметров пришлось бы писать отдельный запрос для каждого случая или конструировать сложные строковые выражения. Параметры же делают код лаконичнее, а логику — прозрачнее. Но как они работают на практике? Какие типы параметров существуют в 1С 8.3 и 1С 8.2? И какие подводные камни ждут новичков? Ответы — в этом руководстве.
Что такое параметры запроса и зачем они нужны
Параметры запроса — это именованные переменные, которые подставляются в текст запроса перед его выполнением. Они позволяют:
- 🔄 Динамически изменять условия — например, передавать даты начала и конца периода из формы отчёта.
- 🔍 Упрощать код — вместо конкатенации строк с условиями (что чревато SQL-инъекциями) использовать безопасные параметры.
- ⚡ Повышать производительность — платформа 1С может кэшировать планы выполнения запросов с параметрами.
- 📊 Создавать универсальные отчёты — один запрос может работать с разными наборами данных.
Простой пример: вам нужно получить список продаж за текущий месяц. Без параметров придётся жёстко прописывать даты в тексте запроса. С параметрами — достаточно передать значения НачалоПериода и КонецПериода из кода:
Запрос.Текст =
"ВЫБРАТЬ
| Продажи.Дата КАК Дата,
| Продажи.Сумма КАК Сумма
|ИЗ
| Документ.Продажа КАК Продажи
|ГДЕ
| Продажи.Дата МЕЖДУ &НачалоПериода И &КонецПериода";
Здесь &НачалоПериода и &КонецПериода — это параметры. Их значения задаются перед выполнением запроса методом УстановитьПараметр().
Типы параметров в запросах 1С
В 1С:Предприятие параметры запроса могут иметь разные типы данных, что влияет на их обработку и форматирование. Основные типы:
| Тип параметра | Пример значения | Особенности |
|---|---|---|
| Число | 100, 3.14 |
Используется для количественных фильтров (например, сумма больше 1000). |
| Строка | "ООО Ромашка" |
Требует кавычек в тексте запроса. Чувствительна к регистру, если не используется функция ВРЕГ(). |
| Дата | '2026-01-01' |
Форматируется как 'ГГГГ-ММ-ДД'. Можно передавать объекты типа Дата из 1С. |
| Булево | ИСТИНА, ЛОЖЬ |
Используется для условий типа ГДЕ Активен = &Флаг. |
| NULL | NULL |
Применяется для проверки на незаполненность (ЕСТЬNULL). |
Важно: если параметр строкового типа содержит апостроф (например, "ОАО 'Альфа'"), платформа автоматически экранирует его, чтобы избежать ошибок синтаксиса. Это избавляет от необходимости ручной обработки специальных символов.
Пример использования параметра типа Дата:
Запрос.Текст = "ВЫБРАТЬ * ИЗ Справочник.Контрагенты ГДЕ ДатаРегистрации > &МинимальнаяДата";
Запрос.УстановитьПараметр("МинимальнаяДата", ТекущаяДата() - 365); // Прошлый год
Если вам нужно передать в запрос массив значений (например, список ID), используйте временные таблицы или конструкцию В(&Список) с параметром строкового типа, содержащим разделённые запятыми значения.
Как установить параметр в запросе: синтаксис и методы
Чтобы передать значение в параметр, используйте метод УстановитьПараметр() объекта Запрос. Синтаксис:
Запрос.УстановитьПараметр(ИмяПараметра, Значение);
Где:
- 📌
ИмяПараметра— строка с именем параметра без знака & (например,"ДатаНачала", а не"&ДатаНачала"). - 📌
Значение— любое допустимое значение соответствующего типа.
Пример с несколькими параметрами:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Номенклатура.Наименование,
| ОстаткиНоменклатуры.Количество
|ИЗ
| Справочник.Номенклатура КАК Номенклатура
| ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ОстаткиНоменклатуры КАК ОстаткиНоменклатуры
| ПО Номенклатура.Ссылка = ОстаткиНоменклатуры.Номенклатура
|ГДЕ
| Номенклатура.Группа = &ГруппаТоваров
| И ОстаткиНоменклатуры.Склад = &ТекущийСклад";
Запрос.УстановитьПараметр("ГруппаТоваров", Справочники.ГруппыНоменклатуры.НайтиПоНаименованию("Электроника"));
Запрос.УстановитьПараметр("ТекущийСклад", Справочники.Склады.ОсновнойСклад);
Также можно передавать параметры через коллекцию параметров:
Параметры = Новый Соответствие;
Параметры.Вставить("МинимальнаяСумма", 10000);
Параметры.Вставить("МаксимальнаяСумма", 50000);
Запрос.УстановитьПараметры(Параметры);
Имена параметров в тексте запроса и при установке значения должны совпадать с учётом регистра! Например, &ДаТа и Дата — это разные параметры.
Практические примеры использования параметров
Рассмотрим реальные сценарии, где параметры запроса незаменимы.
1. Фильтрация по динамическому периоду
Типичная задача для отчётов — выборка данных за период, который пользователь указывает в форме:
Запрос.Текст =
"ВЫБРАТЬ
| Документ.ПоступлениеТоваров.Дата КАК Дата,
| СУММА(Документ.ПоступлениеТоваров.СуммаДокумента) КАК Итого
|ИЗ
| Документ.ПоступлениеТоваров КАК Документ.ПоступлениеТоваров
|ГДЕ
| Документ.ПоступлениеТоваров.Дата МЕЖДУ &ДатаНачала И &ДатаКонца
|СГРУППИРОВАТЬ ПО
| Документ.ПоступлениеТоваров.Дата";
Запрос.УстановитьПараметр("ДатаНачала", Форма.Период.Начало);
Запрос.УстановитьПараметр("ДатаКонца", Форма.Период.Конец);
2. Поиск по частичному совпадению
Пользователь вводит часть названия контрагента — нужно найти все совпадения:
Запрос.Текст =
"ВЫБРАТЬ
| Контрагенты.Ссылка КАК Ссылка,
| Контрагенты.Наименование КАК Наименование
|ИЗ
| Справочник.Контрагенты КАК Контрагенты
|ГДЕ
| ВРЕГ(Контрагенты.Наименование) ПОДОБНО ВРЕГ(&ПоисковаяСтрока)";
Запрос.УстановитьПараметр("ПоисковаяСтрока", "%" + Форма.Поиск.Текст + "%");
Обратите внимание: символы % используются как подстановочные знаки (аналог LIKE в SQL).
3. Условная логика с параметрами
Иногда нужно включать или исключать условия в зависимости от значений параметров. Например, фильтр по складу, который может быть не задан:
Запрос.Текст =
"ВЫБРАТЬ
| Остатки.Номенклатура,
| Остатки.Количество
|ИЗ
| РегистрНакопления.ОстаткиНоменклатуры КАК Остатки
|ГДЕ
| (&Склад IS NULL ИЛИ Остатки.Склад = &Склад)
| И Остатки.Количество > 0";
Если Не СкладЗадан Тогда
Запрос.УстановитьПараметр("Склад", NULL);
Иначе
Запрос.УстановитьПараметр("Склад", ТекущийСклад);
КонецЕсли;
Как работает условие с NULL в примере выше?
В языке запросов 1С конструкция &Склад IS NULL проверяет, что параметр не задан (равен NULL). Таким образом, если склад не указан, условие Остатки.Склад = &Склад игнорируется, и фильтрация по складу не применяется.
Ошибки и нюансы работы с параметрами
Даже опытные разработчики иногда сталкиваются с проблемами при использовании параметров. Вот наиболее распространённые ошибки:
⚠️ Внимание: Если вы передаёте в параметр строкового типа значение с апострофами (например,"ОАО 'Вега'"), платформа 1С автоматически экранирует их. Однако при ручном формировании строки запроса (например, черезСтрЗаменить()) это может привести к синтаксическим ошибкам.
1. Несоответствие типов данных
Если параметр в тексте запроса объявлен как дата ('2026-01-01'), а вы передаёте строку ("01.01.2026"), возникнет ошибка. Всегда следите за соответствием типов:
// Неверно:
Запрос.УстановитьПараметр("ДатаДокумента", "01.01.2026"); // Строка вместо даты
// Правильно:
Запрос.УстановитьПараметр("ДатаДокумента", '2026-01-01'); // Либо объект типа Дата
2. Ошибки с NULL
Параметры с значением NULL требуют особого подхода. Например, такое условие не сработает:
ГДЕ Поле = &Параметр // Если &Параметр = NULL, сравнение вернёт ЛОЖЬ
Вместо этого используйте:
ГДЕ (&Параметр ЕСТЬ NULL ИЛИ Поле = &Параметр)
3. Проблемы с кэшированием
Платформа 1С может кэшировать планы выполнения запросов с параметрами. Если структура данных изменилась (например, добавилось поле), а запрос с теми же параметрами уже выполнялся, может использоваться устаревший план. В таких случаях помогает:
- 🔄 Перезапуск сеанса 1С.
- 🔄 Явная очистка кэша через
ОчиститьКэшЗапросов()(доступно в режиме отладки). - 🔄 Добавление "фиктивного" параметра, который меняется при каждом выполнении (например, текущее время).
⚠️ Внимание: В некоторых конфигурациях (особенно с большим количеством пользователей) чрезмерное использование динамических параметров может приводить к фрагментации кэша и падению производительности. В таких случаях рассмотрите возможность использования временных таблиц.
Параметры vs. временные таблицы: что выбрать
Параметры запроса удобны, но не всегда являются оптимальным решением. Альтернатива — временные таблицы, которые создаются на время выполнения запроса. Когда что использовать?
| Критерий | Параметры | Временные таблицы |
|---|---|---|
| Простота использования | ⭐⭐⭐⭐⭐ | ⭐⭐⭐ |
| Производительность при больших данных | ⭐⭐⭐ | ⭐⭐⭐⭐⭐ |
| Гибкость (сложные условия) | ⭐⭐ | ⭐⭐⭐⭐⭐ |
| Поддержка массивов данных | ❌ Нет | ✅ Да |
Пример, где временные таблицы предпочтительнее:
// Создаём временную таблицу с списком ID
ВТ_СписокТоваров = Новый ВременнаяТаблица;
ВТ_СписокТоваров.Колонки.Добавить("Товар", Новый ОписаниеТипов("СправочникСсылка.Номенклатура"));
Для Каждого Товар Из МассивТоваров Цикл
Строка = ВТ_СписокТоваров.Добавить();
Строка.Товар = Товар;
КонецЦикла;
// Используем её в запросе
Запрос.Текст =
"ВЫБРАТЬ
| Остатки.Номенклатура КАК Товар,
| Остатки.Количество
|ИЗ
| РегистрНакопления.ОстаткиНоменклатуры КАК Остатки
| ВНУТРЕННЕЕ СОЕДИНЕНИЕ &ВТ_СписокТоваров КАК Список
| ПО Остатки.Номенклатура = Список.Товар";
Запрос.УстановитьВременнуюТаблицу("ВТ_СписокТоваров", ВТ_СписокТоваров);
Список товаров/документов содержит более 100 элементов|Нужно применить сложную логику фильтрации (например, иерархию)|Требуется соединить данные из разных источников|Необходимо оптимизировать производительность при больших объёмах данных-->
Оптимизация запросов с параметрами
Параметры могут как ускорить, так и замедлить выполнение запросов. Следующие рекомендации помогут избежать типичных ошибок:
- 🔍 Избегайте избыточных параметров. Каждый параметр увеличивает сложность плана выполнения. Если значение используется один раз, лучше подставить его напрямую.
- ⚡ Используйте индексируемые поля в условиях с параметрами. Например, фильтрация по
Номенклатура.Артикул(индексированное поле) будет быстрее, чем поНоменклатура.ПолноеНаименование. - 📊 Для диапазонов дат используйте параметры начала и конца. Это позволяет платформе эффективно использовать индексы:
ГДЕ Дата МЕЖДУ &ДатаНачала И &ДатаКонца // Оптимально
ГДЕ Дата >= &ДатаНачала И Дата <= &ДатаКонца // Эквивалентно, но менее читаемо
- 🔄 Тестируйте производительность. В 1С:Предприятие можно включить отображение плана выполнения запроса (в режиме отладки) и анализировать, как параметры влияют на него.
Пример оптимизированного запроса с параметрами:
Запрос.Текст =
"ВЫБРАТЬ ПЕРВЫЕ 100
| Продажи.Номенклатура КАК Товар,
| СУММА(Продажи.Количество) КАК Продано
|ИЗ
| Документ.РеализацияТоваров.Товары КАК Продажи
|ГДЕ
| Продажи.Документ.Дата МЕЖДУ &ДатаНачала И &ДатаКонца
| И Продажи.Номенклатура В (&СписокТоваров)
|СГРУППИРОВАТЬ ПО
| Продажи.Номенклатура
|УПОРЯДОЧИТЬ ПО
| Продано УБЫВ";
Запрос.УстановитьПараметр("ДатаНачала", НачалоМесяца(ТекущаяДата()));
Запрос.УстановитьПараметр("ДатаКонца", КонецМесяца(ТекущаяДата()));
Запрос.УстановитьПараметр("СписокТоваров", "123,456,789"); // Список ID через запятую
FAQ: Частые вопросы о параметрах запроса в 1С
Можно ли использовать параметры в выражениях типа КАК или ГДЕ?
Да, параметры можно подставлять в любые части запроса, где допустимы литералы соответствующего типа. Например:
ВЫБРАТЬ
Дата КАК &ИмяПоля, // Параметр как имя колонки
Сумма * &Коэффициент КАК СуммаСУчетомНДС // Параметр в выражении
ИЗ Документ.Продажи
Однако имя поля (&ИмяПоля) должно быть строкой и не содержать пробелов или специальных символов.
Как передать в запрос массив значений (например, список ID)?
Есть два основных способа:
- Через строку с разделёнными запятыми значениями и конструкцию
В(&Список):
Запрос.УстановитьПараметр("Список", "1001,1002,1003");
...
ГДЕ ID В (&Список)
- Через временную таблицу (рекомендуется для больших массивов):
ВТ = Новый ВременнаяТаблица;
ВТ.Колонки.Добавить("ID");
Для Каждого Элемент Из МассивID Цикл
Строка = ВТ.Добавить();
Строка.ID = Элемент;
КонецЦикла;
Запрос.УстановитьВременнуюТаблицу("ВТ_Список", ВТ);
Почему запрос с параметрами работает медленнее, чем без них?
Это может происходить по нескольким причинам:
- 🔹 Платформа 1С не всегда может оптимально кэшировать планы выполнения для запросов с параметрами, особенно если их много.
- 🔹 Параметры могут мешать использованию индексов (например, если в условии используется функция над параметром:
ГДЕ Поле = ВРЕГ(&Параметр)). - 🔹 При передаче
NULLв параметр условие видаПоле = &Параметрникогда не будет истинным (используйтеЕСТЬNULL).
Решение: анализируйте план выполнения запроса в режиме отладки (Запрос.Выполнить().ПланВопроса()).
Можно ли использовать параметры в пакетных запросах?
Да, в пакетных запросах параметры работают так же, как и в обычных. Главное — установить их значения до выполнения пакета:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ * ИЗ Справочник.Контрагенты ГДЕ Наименование ПОДОБНО &Поиск;
ВЫБРАТЬ ТОП 10 * ИЗ Документ.ЗаказыПокупателей УПОРЯДОЧИТЬ ПО Дата УБЫВ";
Запрос.УстановитьПараметр("Поиск", "%ИП%");
Результат = Запрос.ВыполнитьПакет();
Все параметры, используемые в пакете, должны быть установлены до вызова ВыполнитьПакет().
Как избежать SQL-инъекций при работе с параметрами?
В 1С:Предприятие параметры запроса автоматически экранируются, поэтому риск SQL-инъекций минимален. Однако опасность остаётся при:
- 🔹 Динамическом формировании текста запроса через конкатенацию строк (например,
СтрЗаменить()). - 🔹 Использовании пользовательского ввода напрямую в тексте запроса без параметров.
Пример небезопасного кода:
ТекстЗапроса = "ВЫБРАТЬ * ИЗ Документ.Продажи ГДЕ Контрагент = '" + ПользовательскийВвод + "'";
// Если ПользовательскийВвод = "x'; DROP TABLE Документ.Продажи; --", это приведёт к ошибке или утечке данных.
Безопасная альтернатива:
Запрос.Текст = "ВЫБРАТЬ * ИЗ Документ.Продажи ГДЕ Контрагент = &Контрагент";
Запрос.УстановитьПараметр("Контрагент", ПользовательскийВвод);