Работа с данными в платформе 1С:Предприятие невозможна без грамотного использования языка запросов. Часто возникает ситуация, когда жестко прописанные значения в тексте запроса делают код негибким и трудно поддерживаемым. Именно в этот момент разработчик сталкивается с необходимостью внедрить динамические переменные.
Параметры запроса позволяют передавать внешние данные внутрь структуры запроса, делая его универсальным инструментом для выборки информации. Это фундаментальный механизм, который отличает профессиональный код от любительского. Понимание того, как корректно объявить и установить значение параметра, критически важно для любого разработчика, работающего с СКД или встроенными запросами.
В этой статье мы детально разберем все аспекты работы с параметрами, начиная от базового синтаксиса и заканчивая сложными случаями фильтрации по динамическим спискам. Вы узнаете, как избежать типичных ошибок и обеспечить максимальную производительность вашей конфигурации.
Базовый синтаксис объявления параметров
Любой параметр в языке запросов 1С начинается со знака амперсанда &. Это обязательное условие, без соблюдения которого движок запросов просто не распознает переменную как параметр, а попытается найти поле с таким именем в источниках данных. Если такое поле не найдено, система выдаст ошибку компиляции.
Для установки значения параметра используется метод УстановитьПараметр объекта запроса. Этот метод принимает два аргумента: имя параметра (строка без амперсанда) и само значение, которое может быть любого примитивного типа или ссылкой на объект метаданных.
Имя параметра в методе УстановитьПараметр указывается БЕЗ знака амперсанда, в отличие от текста самого запроса.
Рассмотрим простейший пример инициализации. Допустим, нам нужно выбрать документы, принадлежащие конкретному контрагенту. Мы не будем подставлять UUID контрагента прямо в текст запроса, так как это небезопасно и неэффективно.
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| РеализацияТоваровУслуг.Ссылка
|ИЗ
| Документ.РеализацияТоваровУслуг КАК РеализацияТоваровУслуг
|ГДЕ
| РеализацияТоваровУслуг.Контрагент = &Контрагент";
Запрос.УстановитьПараметр("Контрагент", ВыбранныйКонтрагент);
Результат = Запрос.Выполнить;
Обратите внимание на использование символа подстановки в тексте запроса. Платформа автоматически экранирует специальные символы, если они попадут в значение параметра, что защищает от синтаксических ошибок, хотя полноценной защиты от SQL-инъекций в классическом понимании здесь не требуется из-за архитектуры платформы.
Работа со списками значений в условиях
Одной из самых частых задач является фильтрация по списку элементов. Например, пользователю нужно отобрать номенклатуру из определенной группы или документы за выбранный период по нескольким складам. В таких случаях параметр должен представлять собой коллекцию значений.
Для передачи списка в запрос используется объект СписокЗначений или таблица значений. При сравнении поля со списком в условии ГДЕ используется оператор В. Синтаксис остается прежним: Поле В (&ПараметрСписка). Платформа сама разворачивает этот список в набор условий ИЛИ на уровне исполнения.
Создание списка значений программно выглядит следующим образом:
СписокСкладов = Новый СписокЗначений;
СписокСкладов.Добавить(Склад1);
СписокСкладов.Добавить(Склад2);
СписокСкладов.Добавить(Склад3);
Запрос.УстановитьПараметр("СписокСкладов", СписокСкладов);
Важным нюансом является типизация элементов списка. Если поле в базе данных является ссылкой на справочник, то и в СписокЗначений должны быть добавлены именно ссылки, а не строковые представления. Нарушение этого правила приведет к тому, что запрос вернет пустой результат, так как типы данных не совпадут при сравнении.
Также стоит упомянуть о возможности передачи пустого списка. Если коллекция пуста, условие В (&Параметр) всегда будет ложным, и выборка не вернет ни одной строки. Это поведение следует учитывать при построении логических условий с оператором ИЛИ.
Использование параметров даты и времени
Фильтрация по периодам — это основа любой отчетной системы в 1С:Предприятие. При работе с датами необходимо учитывать точность хранения значений в базе данных. Поля типа ДатаВремя могут хранить значения с точностью до секунды или даже меньше, в зависимости от конфигурации СУБД.
Частой ошибкой является попытка выбрать данные за конкретный день, используя только дату начала. Если в базе есть записи с временем 15:30:00, а параметр установлен на 00:00:00, условие Дата >= &НачалоПериода захватит весь день, но условие Дата <= &КонецПериода может их отсечь, если конец периода тоже установлен на 00:00:00 следующего дня.
Почему не получается выбрать данные за последний день месяца?
Проблема часто кроется в том, что конец периода устанавливается ровно на 00:00:00 первого числа следующего месяца. Записи, созданные в течение последнего дня (например, в 12:00), оказываются меньше этого значения и не попадают в выборку. Решение: использовать функцию КОНЕЦПЕРИОДА или вычитать одну секунду/миллисекунду.
Для корректной работы с интервалами рекомендуется использовать специальные функции языка запросов, такие как НАЧАЛОДНЯ, КОНЕЦДНЯ, НАЧАЛОМЕСЯЦА. Они позволяют явно указать границы периода, избегая проблем с временной составляющей.
Запрос.Текст =
"ВЫБРАТЬ
| РегистрНакопления.Продажи.Период
|ИЗ
| РегистрНакопления.Продажи
|ГДЕ
| РегистрНакопления.Продажи.Период МЕЖДУ &НачалоПериода И &КонецПериода";
Запрос.УстановитьПараметр("НачалоПериода", НачалоДня(ДатаНачала));
Запрос.УстановитьПараметр("КонецПериода", КонецДня(ДатаКонца));
Использование конструкции МЕЖДУ.. И.. является синтаксическим сахаром для пары условий >= и <=, но делает код более читаемым. При установке параметров убедитесь, что тип переменной соответствует типу Дата, иначе может возникнуть ошибка преобразования типов.
Параметры в системе компоновки данных (СКД)
При разработке отчетов с использованием СКД логика установки параметров меняется. Здесь параметры объявляются на уровне макета компоновки данных и становятся доступны пользователю через форму настроек. Разработчику не нужно вручную вызывать метод УстановитьПараметр в коде модуля отчета.
Значения параметров в СКД передаются автоматически из формы настроек в запрос. Однако, если вы формируете отчет программно, используя объект КомпоновщикНастроек, вам может потребоваться вручную заполнить коллекцию параметров перед выполнением.
| Объект | Метод работы | Особенность |
|---|---|---|
| Запрос | УстановитьПараметр | Требует явного вызова в коде |
| СКД (Макет) | Параметры в настройках | Заполняются формой автоматически |
| СКД (Программно) | ПараметрыКомпоновкиДанных | Требует создания структуры значений |
В системе компоновки данных параметры могут иметь сложные типы, например, ПолеКомпоновкиДанных. Это позволяет пользователю выбирать, по какому именно полю группировать данные или строить отбор. Реализация такой логики требует внимательной настройки схемы компоновки.
В СКД параметры могут быть не только значениями, но и ссылками на поля макета, что дает пользователю гибкость в управлении структурой отчета.
Ошибка в типе параметра в СКД часто приводит к тому, что отчет просто не формируется или выдает сообщение о невозможности выполнить запрос. Всегда проверяйте соответствие типов в схеме компоновки и в исходных данных.
Оптимизация и влияние на производительность
Неправильное использование параметров может стать узким местом в производительности системы. Главный принцип оптимизации: параметры должны использоваться в условиях отбора, которые могут быть переданы на уровень СУБД. Если условие с параметром вынуждает 1С выгружать все данные в оперативную память для последующей фильтрации, это катастрофически снижает скорость работы.
Особое внимание стоит уделить параметрам, используемым в соединениях (ЛЕВОЕ СОЕДИНЕНИЕ, ВНУТРЕННЕЕ СОЕДИНЕНИЕ). Если параметр участвует в условии соединения, убедитесь, что он не блокирует использование индексов. В некоторых случаях использование временных таблиц с параметрами может быть эффективнее, чем сложное условие в основном запросе.
⚠️ Внимание: Избегайте использования параметров в функциях, применяемых к полям в условии ГДЕ. Например, конструкция
ГДЕ ГОД(Дата) = &Годзапрещает использование индекса по полю Дата. Лучше использовать диапазон дат:ГДЕ Дата МЕЖДУ &НачалоГода И &КонецГода.
Также стоит помнить о лимитах на количество параметров в одном запросе, хотя на практике достигнуть этого предела в типовых задачах крайне сложно. Более актуальной проблемой является сложность плана выполнения запроса при большом количестве значений в параметре-списке.
Для анализа того, как параметры влияют на выполнение, используйте Консоль запросов. Она позволяет увидеть текст запроса после подстановки параметров (режим отладки) и проанализировать план выполнения, предложенный СУБД.
Типичные ошибки и способы их решения
Разработчики часто сталкиваются с ошибкой"Неизвестное имя поля" или"Синтаксическая ошибка", когда забывают поставить амперсанд перед именем параметра в тексте запроса. Другая распространенная проблема — несоответствие регистра имен. В языке запросов 1С имена параметров чувствительны к регистру, если они не совпадают с именами полей метаданных.
Еще одна ошибка связана с передачей Неопределено (Null) в параметр. Если поле в базе данных не допускает пустых значений, а вы передаете в параметр Null, поведение может быть непредсказуемым в зависимости от контекста условия. Для проверки на заполненность лучше использовать оператор ЕСТЬ NULL или специальные функции.
☑️ Диагностика проблем с параметрами
Если вы используете динамический список в параметре, убедитесь, что он не пуст перед установкой. Пустой список в условии В всегда дает ложный результат, что может привести к тому, что отчет покажет отсутствие данных, хотя они есть.
⚠️ Внимание: При передаче строковых параметров, содержащих спецсимволы (кавычки, проценты), платформа обрабатывает их корректно. Однако, если вы формируете текст запроса конкатенацией строк вместо параметров, вы гарантированно получите ошибку или уязвимость. Всегда используйте параметры!
Не забывайте про область видимости параметров. Параметр, объявленный в одном запросе, не виден в другом, даже если они выполняются последовательно в одной транзакции. Каждый объект Запрос имеет свою изолированную коллекцию параметров.
Часто задаваемые вопросы (FAQ)
Можно ли использовать параметр в имени таблицы или поля?
Нет, параметры в языке запросов 1С могут использоваться только вместо значений (констант). Подставлять имена таблиц, полей или других идентификаторов через параметры нельзя. Для динамической смены полей используется механизм виртуальных таблиц или построение текста запроса программно (что менее предпочтительно).
Как передать в параметр текущую дату?
Для этого используйте встроенную функцию ТекущаяДата при установке параметра: Запрос.УстановитьПараметр("Дата", ТекущаяДата). Если нужна только дата без времени, оберните функцию: НачалоДня(ТекущаяДата).
Что делать, если параметр не передается в СКД?
Проверьте, добавлен ли параметр в схему компоновки данных. Если он есть в тексте запроса, но не описан в схеме, СКД не создаст поле для его ввода. Также убедитесь, что имя параметра в схеме точно совпадает с именем в запросе (с учетом регистра).
Можно ли использовать один параметр несколько раз в запросе?
Да, это стандартная практика. Вы устанавливаете значение параметра один раз через УстановитьПараметр, а в тексте запроса можете ссылаться на него &Параметр столько раз, сколько необходимо в разных условиях или полях выборки.
Как передать список значений из формы в запрос?
Если элемент формы — это поле ввода списка, его значение уже является СпискомЗначений. Вы можете передать его напрямую: Запрос.УстановитьПараметр("Список", ЭлементФормы.Значение). Если это табличное поле, предварительно выгрузить данные в список значений.