Параметры запроса 1С — значения, которые платформа подставляет в текст запроса при выполнении. В тексте параметр обозначают амперсандом (&Организация), значение передают методом УстановитьПараметр(). Ниже — рабочие примеры для платформы 8.3: ссылка и дата, список в условии В, таблица значений, граница периода для остатков, ЗНАЧЕНИЕ(), отладка через НайтиПараметры() и параметры СКД. Основы синтаксиса — в статье о языке запросов 1С.
Форма обработки: пользователь выбирает организацию и период, сервер считает проведённые реализации. Объекта Запрос на клиенте нет, поэтому клиентская процедура только проверяет поля и вызывает серверную функцию.
// Модуль формы обработки. Реквизиты формы: Организация, НачалоПериода,
// КонецПериода, КоличествоДокументов, СуммаПродаж
&НаКлиенте
Процедура Рассчитать(Команда)
Если Не ЗначениеЗаполнено(Организация) Или Не ЗначениеЗаполнено(КонецПериода) Тогда
ПоказатьПредупреждение(, "Заполните организацию и конец периода.");
Возврат;
КонецЕсли;
Итоги = ИтогиПродажНаСервере(Организация, НачалоПериода, КонецПериода);
КоличествоДокументов = Итоги.Количество;
СуммаПродаж = Итоги.Сумма;
КонецПроцедуры
&НаСервереБезКонтекста
Функция ИтогиПродажНаСервере(Организация, НачалоПериода, КонецПериода)
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| КОЛИЧЕСТВО(Реализация.Ссылка) КАК Количество,
| ЕСТЬNULL(СУММА(Реализация.СуммаДокумента), 0) КАК Сумма
|ИЗ
| Документ.РеализацияТоваровУслуг КАК Реализация
|ГДЕ
| Реализация.Проведен
| И Реализация.Организация = &Организация
| И Реализация.Дата МЕЖДУ &НачалоПериода И &КонецПериода";
Запрос.УстановитьПараметр("Организация", Организация);
Запрос.УстановитьПараметр("НачалоПериода", НачалоДня(НачалоПериода));
Запрос.УстановитьПараметр("КонецПериода", КонецДня(КонецПериода));
Итоги = Новый Структура("Количество, Сумма", 0, 0);
Выборка = Запрос.Выполнить().Выбрать();
Если Выборка.Следующий() Тогда
ЗаполнитьЗначенияСвойств(Итоги, Выборка);
КонецЕсли;
Возврат Итоги;
КонецФункции
УстановитьПараметр — без него. Регистр букв не важен, один параметр можно использовать в тексте несколько раз.КонецДня() превращает 31.10.2026 0:00:00 в 31.10.2026 23:59:59. Без него МЕЖДУ потеряет документы последнего дня, кроме созданных ровно в полночь.&НаСервереБезКонтекста получает три значения аргументами, данные формы на сервер не уходят.Запрос.Параметры — обычная структура, поэтому Запрос.Параметры.Вставить("Организация", Организация) равносильно УстановитьПараметр. Параметр, которого нет в тексте, ошибки не вызывает.Склеивать значения с текстом запроса нельзя:
Строка(Организация) вернёт наименование;Строка(1234.5) даст «1 234,5», и текст сломается;| Тип значения | Где в тексте | Что передать |
|---|---|---|
| Ссылка | Т.Склад = &Склад | ссылку на элемент или документ |
| Дата | Т.Дата МЕЖДУ &Начало И &Конец | НачалоДня(), КонецДня() |
| Число, Строка, Булево | Т.Количество > &Порог | значение того же типа, что поле |
| Массив, ФиксированныйМассив, СписокЗначений | Т.Склад В (&Склады) | коллекцию значений |
| ТаблицаЗначений | ИЗ &Таблица КАК Т | таблицу с типизированными колонками |
| Граница, МоментВремени | Остатки(&Период, …) | Новый Граница(МоментВремени(), ВидГраницы.Включая) |
| Тип | ТИПЗНАЧЕНИЯ(Т.Регистратор) = &ТипДокумента | Тип("ДокументСсылка.РеализацияТоваровУслуг") |
Параметр подставляет только значение. Имя таблицы базы, имя поля или число в ВЫБРАТЬ ПЕРВЫЕ параметром не задать — это часть текста. Зато параметр допустим в списке полей: ВЫБРАТЬ &Организация КАК Организация.
Частая ошибка — запрос в цикле по строкам документа. Цены всех товаров получают одним запросом, передав массив номенклатуры в условие виртуальной таблицы.
// Общий модуль (сервер). Регистр ЦеныНоменклатуры: измерения ВидЦены, Номенклатура; ресурс Цена.
// Товары — табличная часть или таблица значений с колонкой Номенклатура
Функция ЦеныТоваров(Товары, ВидЦены, НаДату) Экспорт
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Цены.Номенклатура КАК Номенклатура,
| Цены.Цена КАК Цена
|ИЗ
| РегистрСведений.ЦеныНоменклатуры.СрезПоследних(
| &НаДату,
| ВидЦены = &ВидЦены
| И Номенклатура В (&СписокНоменклатуры)) КАК Цены";
Запрос.УстановитьПараметр("НаДату", НаДату);
Запрос.УстановитьПараметр("ВидЦены", ВидЦены);
Запрос.УстановитьПараметр("СписокНоменклатуры", Товары.ВыгрузитьКолонку("Номенклатура"));
Цены = Новый Соответствие;
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
Цены.Вставить(Выборка.Номенклатура, Выборка.Цена);
КонецЦикла;
Возврат Цены;
КонецФункции
ВыгрузитьКолонку() есть у табличной части и у таблицы значений, она возвращает Массив. Повторы в массиве не мешают.СписокЗначений (например, склады, отмеченные пользователем на форме) и ФиксированныйМассив — текст запроса не меняется.СрезПоследних, а не в ГДЕ: срез строится только по нужным товарам, а не по всему регистру.Номенклатура В ИЕРАРХИИ (&Группы): в параметр можно передать и одну группу, и массив.Данные из файла или обмена передают в запрос таблицей значений и соединяют с таблицами базы. Пример сопоставляет артикулы из файла с номенклатурой.
// Общий модуль (сервер). СтрокиФайла — массив структур с ключами Артикул и Количество
Функция СопоставитьПоАртикулам(СтрокиФайла) Экспорт
ТаблицаЗагрузки = Новый ТаблицаЗначений;
ТаблицаЗагрузки.Колонки.Добавить("Артикул", Новый ОписаниеТипов("Строка", , Новый КвалификаторыСтроки(50)));
ТаблицаЗагрузки.Колонки.Добавить("Количество", Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(15, 3)));
Для Каждого СтрокаФайла Из СтрокиФайла Цикл
НоваяСтрока = ТаблицаЗагрузки.Добавить();
НоваяСтрока.Артикул = СокрЛП(СтрокаФайла.Артикул);
НоваяСтрока.Количество = СтрокаФайла.Количество;
КонецЦикла;
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Загрузка.Артикул КАК Артикул,
| Загрузка.Количество КАК Количество
|ПОМЕСТИТЬ ВТЗагрузка
|ИЗ
| &ТаблицаЗагрузки КАК Загрузка
|ИНДЕКСИРОВАТЬ ПО
| Артикул
|;
|
|ВЫБРАТЬ
| ВТЗагрузка.Артикул КАК Артикул,
| ВТЗагрузка.Количество КАК Количество,
| ЕСТЬNULL(СпрНоменклатура.Ссылка, ЗНАЧЕНИЕ(Справочник.Номенклатура.ПустаяСсылка)) КАК Номенклатура
|ИЗ
| ВТЗагрузка КАК ВТЗагрузка
| ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Номенклатура КАК СпрНоменклатура
| ПО ВТЗагрузка.Артикул = СпрНоменклатура.Артикул
| И (НЕ СпрНоменклатура.ПометкаУдаления)";
Запрос.УстановитьПараметр("ТаблицаЗагрузки", ТаблицаЗагрузки);
Возврат Запрос.Выполнить().Выгрузить();
КонецФункции
ОписаниеТипов. Колонка без типа или с типом, которого нет в языке запросов (Структура, вложенная ТаблицаЗначений), вызывает ошибку при выполнении.ПО и ГДЕ.ПОМЕСТИТЬ) с индексом по полю соединения, а соединяют уже ВТ.Товары.Выгрузить(, "Номенклатура, Количество"): колонки выгруженной таблицы уже типизированы по метаданным.В по нескольким полям пишут вложенный запрос к ВТ: (Т.Номенклатура, Т.Склад) В (ВЫБРАТЬ ВТ.Номенклатура, ВТ.Склад ИЗ ВТ КАК ВТ).У виртуальных таблиц регистров первый параметр — период. От типа переданного значения зависит, попадут ли в расчёт движения на граничный момент.
| Значение периода в Остатки() | Что войдёт в остаток |
|---|---|
Дата, например НачалоДня(Дата) | движения строго раньше этого момента — остаток на начало дня |
Новый Граница(КонецДня(Дата), ВидГраницы.Включая) | весь день включительно — остаток на конец дня |
МоментВремени() документа | всё до документа, без его собственных движений |
Новый Граница(МоментВремени(), ВидГраницы.Включая) | вместе с движениями самого документа |
ничего: Остатки(, Условие) | все движения, в том числе датированные будущим |
Типичный случай — контроль остатков при проведении: движения записываются, затем запрос проверяет, не ушёл ли остаток в минус на момент документа.
// Модуль объекта документа: реквизит Склад, табличная часть Товары (Номенклатура, Количество).
// Регистр накопления ТоварыНаСкладах: измерения Склад, Номенклатура; ресурс Количество
Процедура ОбработкаПроведения(Отказ, РежимПроведения)
Движения.ТоварыНаСкладах.Записывать = Истина;
Для Каждого СтрокаТовара Из Товары Цикл
Движение = Движения.ТоварыНаСкладах.ДобавитьРасход();
Движение.Период = Дата;
Движение.Склад = Склад;
Движение.Номенклатура = СтрокаТовара.Номенклатура;
Движение.Количество = СтрокаТовара.Количество;
КонецЦикла;
Движения.ТоварыНаСкладах.БлокироватьДляИзменения = Истина;
Движения.ТоварыНаСкладах.Записать();
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Остатки.Номенклатура КАК Номенклатура,
| -Остатки.КоличествоОстаток КАК Нехватка
|ИЗ
| РегистрНакопления.ТоварыНаСкладах.Остатки(
| &Граница,
| Склад = &Склад
| И Номенклатура В (&СписокНоменклатуры)) КАК Остатки
|ГДЕ
| Остатки.КоличествоОстаток < 0";
Запрос.УстановитьПараметр("Граница", Новый Граница(МоментВремени(), ВидГраницы.Включая));
Запрос.УстановитьПараметр("Склад", Склад);
Запрос.УстановитьПараметр("СписокНоменклатуры", Товары.ВыгрузитьКолонку("Номенклатура"));
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
Сообщение = Новый СообщениеПользователю;
Сообщение.Текст = СтрШаблон("Не хватает товара %1: %2", Выборка.Номенклатура, Выборка.Нехватка);
Сообщение.Сообщить();
Отказ = Истина;
КонецЦикла;
КонецПроцедуры
МоментВремени() — дата и ссылка документа. С видом границы Включая остаток считается вместе с только что записанным расходом, поэтому КоличествоОстаток < 0 и есть нехватка.БлокироватьДляИзменения накладывает управляемую блокировку по измерениям записываемого набора: два документа не спишут один остаток одновременно.КоличествоОстаток остаётся в ГДЕ.Значения, известные при разработке, — элементы перечислений, предопределённые элементы, пустые ссылки — пишут в текст через ЗНАЧЕНИЕ(). Параметр нужен для того, что известно только при выполнении: выбор пользователя, реквизит документа, текущая дата.
// Общий модуль (сервер). Пустой Контрагент или Менеджер означает «без отбора»
Функция ОткрытыеЗаказы(Контрагент = Неопределено, Менеджер = Неопределено) Экспорт
Условия = Новый Массив;
Условия.Добавить("Заказы.Проведен");
Условия.Добавить("Заказы.Статус <> ЗНАЧЕНИЕ(Перечисление.СтатусыЗаказовКлиентов.Закрыт)");
Если ЗначениеЗаполнено(Контрагент) Тогда
Условия.Добавить("Заказы.Контрагент = &Контрагент");
КонецЕсли;
Если ЗначениеЗаполнено(Менеджер) Тогда
Условия.Добавить("Заказы.Менеджер = &Менеджер");
КонецЕсли;
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Заказы.Ссылка КАК Ссылка,
| Заказы.Контрагент КАК Контрагент,
| Заказы.СуммаДокумента КАК Сумма
|ИЗ
| Документ.ЗаказКлиента КАК Заказы
|ГДЕ
| " + СтрСоединить(Условия, Символы.ПС + Символы.Таб + "И ") + "
|
|УПОРЯДОЧИТЬ ПО
| Заказы.Дата";
Запрос.УстановитьПараметр("Контрагент", Контрагент);
Запрос.УстановитьПараметр("Менеджер", Менеджер);
Возврат Запрос.Выполнить().Выгрузить();
КонецФункции
ЗНАЧЕНИЕ() принимает значения перечислений, предопределённые элементы и пустые ссылки; обычный элемент справочника передают параметром. Опечатка в имени внутри ЗНАЧЕНИЕ() всплывёт при выполнении запроса, а не при проверке модуля.(Заказы.Менеджер = &Менеджер ИЛИ &Менеджер = ЗНАЧЕНИЕ(Справочник.Пользователи.ПустаяСсылка)) тоже работает, но ИЛИ мешает СУБД использовать индекс. О проверке пустых значений — в статье про пустую ссылку в запросе.Метод НайтиПараметры() разбирает текст и возвращает описание каждого параметра: имя и тип, который платформа ожидает по контексту. Если сравнить его с Запрос.Параметры, незаданный параметр или значение не того типа видны сразу.
// Общий модуль (сервер)
Функция ОтчетПоПараметрамЗапроса(Запрос) Экспорт
Попытка
ОписанияПараметров = Запрос.НайтиПараметры();
Исключение
Возврат "Текст запроса не разобран: " + КраткоеПредставлениеОшибки(ИнформацияОбОшибке());
КонецПопытки;
Строки = Новый Массив;
Для Каждого ОписаниеПараметра Из ОписанияПараметров Цикл
Значение = Неопределено;
Если Запрос.Параметры.Свойство(ОписаниеПараметра.Имя, Значение) Тогда
Факт = СтрШаблон("%1 (%2)", Значение, ТипЗнч(Значение));
Иначе
Факт = "НЕ ЗАДАН";
КонецЕсли;
Строки.Добавить(СтрШаблон("&%1: ожидается %2, передано %3",
ОписаниеПараметра.Имя, ОписаниеПараметра.ТипЗначения, Факт));
КонецЦикла;
Возврат СтрСоединить(Строки, Символы.ПС);
КонецФункции
Функция ВыполнитьЗапросСПроверкой(Запрос) Экспорт
Попытка
Возврат Запрос.Выполнить();
Исключение
ВызватьИсключение КраткоеПредставлениеОшибки(ИнформацияОбОшибке())
+ Символы.ПС + ОтчетПоПараметрамЗапроса(Запрос);
КонецПопытки;
КонецФункции
Попытка.Свойство(Имя, Значение) за один вызов проверяет наличие параметра и получает его значение.Запрос.Выполнить() вызывают ВыполнитьЗапросСПроверкой(): в тексте исключения появится список параметров с пометкой «НЕ ЗАДАН».В схеме компоновки данных текст набора тот же, но значение параметра хранится в настройках, а запрос выполняет процессор компоновки.
| Запрос | СКД | |
|---|---|---|
| Откуда берётся | &Имя в тексте | из текста набора сам попадает на вкладку «Параметры» схемы |
| Кто задаёт значение | код: УстановитьПараметр | пользователь в настройках отчёта или код через ПараметрыДанных |
| Свойства | только значение | тип, заголовок, значение по умолчанию, список значений, ограничение доступности, выражение |
// Общий модуль (сервер). Схема — например, Отчеты.Продажи.ПолучитьМакет("ОсновнаяСхемаКомпоновкиДанных")
Функция ДанныеСхемыКомпоновки(Схема, Организация) Экспорт
Настройки = Схема.НастройкиПоУмолчанию;
Настройки.ПараметрыДанных.УстановитьЗначениеПараметра("Организация", Организация);
КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
Макет = КомпоновщикМакета.Выполнить(Схема, Настройки, , ,
Тип("ГенераторМакетаКомпоновкиДанныхДляКоллекцииЗначений"));
Процессор = Новый ПроцессорКомпоновкиДанных;
Процессор.Инициализировать(Макет);
Результат = Новый ТаблицаЗначений;
ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВКоллекциюЗначений;
ПроцессорВывода.УстановитьОбъект(Результат);
ПроцессорВывода.Вывести(Процессор);
Возврат Результат;
КонецФункции
ПараметрыДанных настроек: объект запроса создаётся внутри компоновки, и вызвать УстановитьПараметр не у чего. Имя совпадает с вкладкой «Параметры» схемы, без амперсанда.УстановитьПараметр не вызван или имя в коде отличается от имени в тексте. Функция ОтчетПоПараметрамЗапроса покажет, какой именно.Реализация.Контрагент = Покупатель. Если имя совпало с полем источника, ошибки не будет вовсе — поле сравнится само с собой, и отбор молча пропадёт.ОписаниеТипов.КонецДня() или Граница.В ушёл пустой массив, в ссылочное поле — строка с наименованием, в обязательный отбор — пустая ссылка. Проверяйте значения до выполнения.Остатки(&Граница, КоличествоОстаток > 0) не сработает: там допустимы только измерения, ресурс фильтруют в ГДЕ.Конструктор значения не хранит, он пишет &Имя в текст. При перетаскивании поля на вкладку «Условия» создаётся условие вида Поле = &Поле, параметры виртуальных таблиц задаются отдельной кнопкой. Значения передают кодом или на вкладке параметров консоли запросов.
Нет, параметр подставляет только значение в выражение. Если число или имя таблицы меняются, текст собирают из констант кода, как условия в примере с заказами, но не из пользовательского ввода.
Нет. Параметры хранятся в объекте Запрос: вызовите УстановитьПараметр с новым значением и выполните запрос ещё раз. Но вместо запроса на каждую строку документа лучше один раз передать массив.
В коде — Дата(1, 1, 1) и Справочники.Склады.ПустаяСсылка() через параметр. В тексте без параметра — ДАТАВРЕМЯ(1, 1, 1) и ЗНАЧЕНИЕ(Справочник.Склады.ПустаяСсылка).
Если отчёт или обработка обросли десятком параметров, временными таблицами и контролем остатков, а разбираться некогда, закажите разработку отчётов и обработок 1С. Опишите задачу на странице «Разместить задание» — исполнители оценят её под вашу конфигурацию.
Станьте частью сообщества!
Войдите или зарегистрируйтесь, и вы сможете участвовать в обсуждениях.