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

Многие разработчики сталкиваются с проблемой: как корректно обработать ситуацию, когда параметр не передан? Should we использовать ЗНАЧЕНИЕЗАПОЛНЕНО() или проверять на НЕ ОПРЕДЕЛЕНО? А как быть с типовыми запросами в управляемых формах, где параметры приходят из реквизитов? В этой статье разберём все способы — от базового синтаксиса до продвинутых техник с примерами кода и типичными ошибками.

Особое внимание уделим трем ключевым подходам:

  1. Использование ЗНАЧЕНИЕЗАПОЛНЕНО() для проверки параметров.
  2. Применение конструкции ВЫБРАТЬ ... ГДЕ ... ИЛИ НЕ ЗНАЧЕНИЕЗАПОЛНЕНО(Параметр).
  3. Динамическое формирование текста запроса с учетом наличия параметров.

Каждый метод имеет свои плюсы и минусы, которые зависят от задачи и версии .

📊 Какой способ обработки необязательных параметров вы используете чаще?
ЗНАЧЕНИЕЗАПОЛНЕНО()
Динамический текст запроса
Конструкцию ГДЕ с ИЛИ
Другой вариант

1. Базовый синтаксис: ЗНАЧЕНИЕЗАПОЛНЕНО()

Самый распространённый способ проверки необязательных параметров — функция ЗНАЧЕНИЕЗАПОЛНЕНО(). Она возвращает ИСТИНА, если параметр передан и не равен NULL (или НЕ ОПРЕДЕЛЕНО в новых версиях платформы). Этот метод подходит для большинства случаев, особенно когда параметры передаются из форм или других процедур.

Пример использования в запросе:

ВЫБРАТЬ

Товары.Наименование,

Товары.Артикул

ИЗ

Справочник.Товары КАК Товары

ГДЕ

(&ПараметрКатегория = ЗНАЧЕНИЕ(Справочник.КатегорииТоваров.ПустаяСсылка())

ИЛИ Товары.Категория = &ПараметрКатегория)

И (&ПараметрПоставщик = ЗНАЧЕНИЕ(Справочник.Поставщики.ПустаяСсылка())

ИЛИ Товары.ОсновнойПоставщик = &ПараметрПоставщик)

Обратите внимание на конструкцию ИЛИ — она позволяет игнорировать условие, если параметр не передан. Однако такой подход может усложнить чтение кода при большом количестве фильтров. Альтернатива — динамическое формирование текста запроса (разберём далее).

⚠️ Внимание: В платформе 1С:Предприятие 8.3.20+ появилось ключевое слово НЕ ОПРЕДЕЛЕНО, которое более корректно обрабатывает неинициализированные параметры. Для старых версий используйте ЗНАЧЕНИЕЗАПОЛНЕНО().
  • ✅ Простота реализации — не требует сложной логики.
  • ✅ Совместимость со всеми версиями платформы.
  • ❌ Может снижать производительность при большом количестве параметров.
  • ❌ Код становится громоздким, если фильтров больше 3-4.

2. Динамическое формирование текста запроса

Если параметров много или они часто меняются, целесообразно формировать текст запроса динамически — добавляя условия только для тех параметров, которые переданы. Этот подход требует больше кода, но делает запрос более читаемым и производительным.

Пример реализации:

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

|ВЫБРАТЬ

| Товары.Наименование,

| Товары.Артикул

|ИЗ

| Справочник.Товары КАК Товары

|ГДЕ

| 1 = 1";

// Добавляем условия только для заполненных параметров

Если ЗНАЧЕНИЕЗАПОЛНЕНО(ПараметрКатегория) Тогда

ТекстЗапроса = ТекстЗапроса + "

| И Товары.Категория = &ПараметрКатегория";

КонецЕсли;

Если ЗНАЧЕНИЕЗАПОЛНЕНО(ПараметрПоставщик) Тогда

ТекстЗапроса = ТекстЗапроса + "

| И Товары.ОсновнойПоставщик = &ПараметрПоставщик";

КонецЕсли;

Запрос = Новый Запрос(ТекстЗапроса);

Запрос.УстановитьПараметр("ПараметрКатегория", ПараметрКатегория);

Запрос.УстановитьПараметр("ПараметрПоставщик", ПараметрПоставщик);

Такой подход особенно полезен для сложных отчётов, где фильтры задаются пользователем через форму. Однако здесь важно следить за синтаксической корректностью — например, не забывать про оператор И перед каждым новым условием.

💡

Используйте символьную метку 1 = 1 в начале условия ГДЕ, чтобы упростить добавление динамических фильтров. Это избавит от необходимости проверять, нужно ли ставить первое И.

Способ Плюсы Минусы Когда использовать
ЗНАЧЕНИЕЗАПОЛНЕНО() в условии Простота, совместимость Громоздкий код при многих параметрах Простые запросы с 1-3 фильтрами
Динамический текст Читаемость, производительность Больше кода, риск синтаксических ошибок Сложные отчёты с множеством фильтров
НЕ ОПРЕДЕЛЕНО (8.3.20+) Более корректная проверка Не работает в старых версиях Новые проекты на актуальных платформах

3. Использование НЕ ОПРЕДЕЛЕНО в новых версиях 1С

Начиная с версии 1С:Предприятие 8.3.20, появилась возможность проверять параметры на НЕ ОПРЕДЕЛЕНО. Это более надёжный способ, чем ЗНАЧЕНИЕЗАПОЛНЕНО(), так как он корректно обрабатывает случаи, когда параметр не просто пуст, а вообще не инициализирован.

Пример кода:

Если НЕ ОПРЕДЕЛЕНО(ПараметрКатегория) Тогда

ПараметрКатегория = НеопределённоеЗначение;

КонецЕсли;

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

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

|ВЫБРАТЬ

| Товары.Наименование

|ИЗ

| Справочник.Товары КАК Товары

|ГДЕ

| (&ПараметрКатегория = ЗНАЧЕНИЕ(Справочник.КатегорииТоваров.ПустаяСсылка())

| ИЛИ Товары.Категория = &ПараметрКатегория)";

Важно: НЕ ОПРЕДЕЛЕНО работает только с переменными, объявленными через Перем или в модулях объектов. Для параметров процедур/функций используйте ЗНАЧЕНИЕЗАПОЛНЕНО().

⚠️ Внимание: При использовании НЕ ОПРЕДЕЛЕНО в управляемых формах убедитесь, что параметры передаются через ПараметрыВыполнения корректно. В некоторых случаях неинициализированные параметры могут приводить к ошибкам при компиляции запроса.

4. Обработка необязательных параметров в управляемых формах

В управляемых формах параметры часто приходят из реквизитов или полей ввода. Здесь важно учитывать, что пустое значение поля не всегда эквивалентно НЕ ОПРЕДЕЛЕНО. Например, поле типа СправочникСсылка может содержать пустую ссылку, а не NULL.

Пример обработки параметров из формы:

Процедура СформироватьОтчёт(Команда)

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

// Получаем значения из формы

ПараметрДаты = ЭлементыФормы.Период.Значение;

ПараметрКонтрагент = ЭлементыФормы.Контрагент.Значение;

// Проверяем заполненность

Если НЕ ЗначениеЗаполнено(ПараметрДаты.Начало) Тогда

ПараметрДаты.Начало = НачалоДня(ТекущаяДата() - 365);

КонецЕсли;

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

|ВЫБРАТЬ

| Документ.Дата,

| Документ.Сумма

|ИЗ

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

|ГДЕ

| Документ.Дата >= &НачалоПериода

| " + ?(ЗначениеЗаполнено(ПараметрКонтрагент), "

| И Документ.Контрагент = &Контрагент", "");

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

Запрос.УстановитьПараметр("НачалоПериода", ПараметрДаты.Начало);

Если ЗначениеЗаполнено(ПараметрКонтрагент) Тогда

Запрос.УстановитьПараметр("Контрагент", ПараметрКонтрагент);

КонецЕсли;

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

КонецПроцедуры

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

Получить значения из элементов формы|Проверить на ЗначениеЗаполнено()|Инициализировать параметры по умолчанию|Добавить условия в запрос динамически|Установить параметры перед выполнением-->

5. Типичные ошибки и как их избежать

При работе с необязательными параметрами разработчики часто допускают ошибки, которые приводят к некорректным результатам или падению производительности. Рассмотрим наиболее распространённые из них:

  • 🚫 Игнорирование типа параметра: Если параметр имеет тип СправочникСсылка, а в запросе сравнивается с NULL, может возникнуть ошибка. Всегда используйте ЗНАЧЕНИЕ(Справочник.Имя.ПустаяСсылка()) для сравнения.
  • 🚫 Избыточные проверки: Не нужно проверять параметр на заполненность несколько раз. Достаточно одной проверки перед формированием запроса.
  • 🚫 Неучтённые NULL в результатах: Если параметр может быть NULL, но в запросе используется в вычислениях (например, в ВЫБОР КОГДА), добавьте обработку через ЕСТЬNULL().
  • 🚫 Забытые УстановитьПараметр(): Динамически добавленное условие требует установки параметра, иначе запрос упадёт с ошибкой.

Пример ошибки и её исправления:

// ОШИБКА: Сравнение со ссылкой без проверки на NULL

ГДЕ Товары.Категория = &ПараметрКатегория

// ПРАВИЛЬНО:

ГДЕ (&ПараметрКатегория = ЗНАЧЕНИЕ(Справочник.КатегорииТоваров.ПустаяСсылка())

ИЛИ Товары.Категория = &ПараметрКатегория)

Что будет, если не обработать необязательный параметр?

Если параметр не обработан, а в запросе используется условие вида ГДЕ Поле = &Параметр, то при отсутствии параметра выдаст ошибку "Неопределённое значение параметра запроса". В лучшем случае запрос вернёт пустой результат, в худшем — прервёт выполнение с исключением.

6. Продвинутые техники: параметры по умолчанию и кэширование

Для оптимизации работы с необязательными параметрами можно использовать значения по умолчанию и кэширование запросов. Например, если параметр не передан, подставлять стандартное значение (текущая дата, пустая ссылка, нулевое число).

Пример с кэшированием:

Процедура ПолучитьДанные(ПараметрКатегория = Неопределено, ПараметрДаты = Неопределено)

// Устанавливаем значения по умолчанию

Если НЕ ЗначениеЗаполнено(ПараметрДаты) Тогда

ПараметрДаты = ТекущаяДата();

КонецЕсли;

КлючКэша = "ЗапросТоваров_" +

?(ЗначениеЗаполнено(ПараметрКатегория), ПараметрКатегория.УникальныйИдентификатор(), "ВсеКатегории") + "_" +

Формат(ПараметрДаты, "ДФ=yyyyMMdd");

// Проверяем кэш

Если Кэш.СуществуетКлюч(КлючКэша) Тогда

Возврат Кэш.Получить(КлючКэша);

КонецЕсли;

// Формируем и выполняем запрос

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

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

|ВЫБРАТЬ

| Товары.Наименование

|ИЗ

| Справочник.Товары КАК Товары

|ГДЕ

| Товары.ДатаПоступления <= &МаксимальнаяДата

| " + ?(ЗначениеЗаполнено(ПараметрКатегория), "

| И Товары.Категория = &Категория", "");

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

Если ЗначениеЗаполнено(ПараметрКатегория) Тогда

Запрос.УстановитьПараметр("Категория", ПараметрКатегория);

КонецЕсли;

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

Кэш.Добавить(КлючКэша, Результат);

Возврат Результат;

КонецПроцедуры

Такой подход сокращает количество повторных выполнений одинаковых запросов, что особенно актуально для веб-сервисов или фоновых задач.

💡

Использование значений по умолчанию и кэширования запросов с необязательными параметрами может увеличить производительность системы на 30-50% при частых повторных обращениях.

7. Сравнение подходов: какой выбрать?

Выбор метода обработки необязательных параметров зависит от нескольких факторов:

  • 📌 Сложность запроса: Для простых запросов с 1-2 параметрами подойдёт ЗНАЧЕНИЕЗАПОЛНЕНО(). Для сложных — динамическое формирование.
  • 📌 Версия платформы: В 1С 8.3.20+ предпочтительнее НЕ ОПРЕДЕЛЕНО.
  • 📌 Источник параметров: В управляемых формах удобнее динамический текст, в отчётах — комбинированный подход.
  • 📌 Производительность: Динамические запросы быстрее, но требуют больше кода.

Рекомендации по выбору:

Критерий ЗНАЧЕНИЕЗАПОЛНЕНО() Динамический текст НЕ ОПРЕДЕЛЕНО
Простота кода ⭐⭐⭐⭐⭐ ⭐⭐ ⭐⭐⭐⭐
Производительность ⭐⭐ ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐
Совместимость ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐⭐ ⭐⭐ (только 8.3.20+)
⚠️ Внимание: В некоторых конфигурациях (например, 1С:ERP или 1С:УТ 11) стандартные отчёты уже содержат механизмы обработки необязательных параметров. Перед изменением кода проверьте, не переопределяете ли вы существующую логику.

FAQ: Частые вопросы по необязательным параметрам в 1С

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

Используйте свойство Значение элемента формы и проверяйте его на заполненность через ЗначениеЗаполнено(). Пример:

Параметр = ЭлементыФормы.ПолеВвода.Значение;

Если НЕ ЗначениеЗаполнено(Параметр) Тогда

Параметр = Неопределено; // или значение по умолчанию

КонецЕсли;

Почему запрос падает с ошибкой "Неопределённое значение параметра", если я использовал ЗНАЧЕНИЕЗАПОЛНЕНО()?

Ошибка возникает, если вы добавили условие с параметром в текст запроса, но не установили его через УстановитьПараметр(). Например:

ТекстЗапроса = "ГДЕ Поле = &Параметр";

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

// Забыли установить параметр!

// Запрос.УстановитьПараметр("Параметр", Значение);

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

Можно ли использовать необязательные параметры в пакетных запросах?

Да, но нужно учитывать, что параметры в пакетных запросах устанавливаются для всех запросов в пакете. Пример:

Запрос1 = Новый Запрос("ВЫБРАТЬ 1 ГДЕ 1 = &Флаг");

Запрос2 = Новый Запрос("ВЫБРАТЬ 2 ГДЕ 2 = &Флаг");

Пакет = Новый ПакетЗапросов;

Пакет.Добавить(Запрос1);

Пакет.Добавить(Запрос2);

Пакет.УстановитьПараметр("Флаг", Истина);

Результат = Пакет.Выполнить();

Если параметр необязательный, установите его значение по умолчанию перед добавлением в пакет.

Как обработать необязательный параметр типа "Массив"?

Для массивов используйте проверку ЗначениеЗаполнено() и функцию В() в запросе:

Если НЕ ЗначениеЗаполнено(МассивИД) Тогда

МассивИД = Новый Массив(); // или массив с одним элементом по умолчанию

КонецЕсли;

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

|ВЫБРАТЬ

| Элементы.Наименование

|ИЗ

| Справочник.Элементы КАК Элементы

|ГДЕ

| " + ?(МассивИД.Количество() > 0, "

| Элементы.Ссылка В (&МассивИД)", "

| 1 = 1");

Влияют ли необязательные параметры на производительность запросов?

Да, но влияние зависит от подхода:

  • ЗНАЧЕНИЕЗАПОЛНЕНО() в условиях может замедлить запрос, так как проверяет каждое условие.
  • Динамический текст запроса обычно быстрее, так как содержит только актуальные условия.
  • Использование НЕ ОПРЕДЕЛЕНО не влияет на производительность напрямую, но упрощает код.

Для критичных по скорости запросов тестируйте оба подхода и сравнивайте планы выполнения.