При работе в конфигурациях на платформе 1С:Предприятие, особенно в таких масштабных и зрелых решениях, как УСО 1.2 (Управление строительной организацией) или УПП 1.3, разработчики часто сталкиваются с необходимостью формирования текста запроса динамически. Однако стандартный инструмент — Конструктор запроса — имеет свои жесткие ограничения. Рассмотрим подробнее, почему попытка открыть программно сформированную строку в конструкторе приводит к синтаксической ошибке и как правильно организовать работу с такими запросами.
Проанализируем ситуацию, представленную в вопросе. Разработчик пытается использовать тернарный оператор ?() прямо внутри строковой переменной, определяющей текст запроса. С точки зрения встроенного языка 1С, такая конструкция абсолютно легитимна:
| ГДЕ "+?(ТолькоБезАктов, "ИсторияПоДоговорамСрезПоследних.Действует И (НЕ ИсторияПоДоговорамСрезПоследних.ЕстьАкт)", "((ИсторияПоДоговорамСрезПоследних.Действует И НЕ ИсторияПоДоговорамСрезПоследних.ЕстьАкт) ИЛИ (НЕ ИсторияПоДоговорамСрезПоследних.Действует И ИсторияПоДоговорамСрезПоследних.ЕстьАкт))")+"
| ) КАК ДействующиеДоговора
Однако, когда мы нажимаем правую кнопку мыши и выбираем Конструктор запроса, платформа пытается распарсить эту строку. Выясним причину неудачи: визуальный конструктор запросов умеет работать только со статическим текстом. Он не является интерпретатором кода и не может выполнить функцию ?() или произвести конкатенацию строк с помощью оператора + в момент проектирования. Для него текст запроса обрывается на первой же закрывающей кавычке, а всё, что идет дальше (плюсы, скобки, переменные), воспринимается как мусор, не относящийся к языку запросов.
Самый правильный и «чистый» способ — это уйти от динамического склеивания строк в пользу передачи параметров. Это позволит конструктору запроса видеть структуру целиком, а SQL-серверу — эффективно кэшировать план выполнения запроса. Разберем по шагам, как преобразовать код с тернарным оператором в статический запрос с параметром.
Вместо того чтобы менять сам текст ГДЕ, мы опишем универсальное логическое условие, которое будет зависеть от переданного булева значения &ТолькоБезАктов. Наш запрос в конструкторе будет выглядеть так:
ГДЕ
(&ТолькоБезАктов = ИСТИНА
И ИсторияПоДоговорамСрезПоследних.Действует
И НЕ ИсторияПоДоговорамСрезПоследних.ЕстьАкт)
ИЛИ
(&ТолькоБезАктов = ЛОЖЬ
И (ИсторияПоДоговорамСрезПоследних.Действует <> ИсторияПоДоговорамСрезПоследних.ЕстьАкт))
После этого в коде 1С нам достаточно просто установить параметр:
Запрос.УстановитьПараметр("ТолькоБезАктов", ТолькоБезАктов);
Преимущества этого подхода:
Если по каким-то причинам вы не можете изменить логику на использование параметров (например, запрос слишком сложный или условия формируются крайне динамично), рассмотрим метод временного комментирования. Это практический прием, позволяющий быстро внести правки в визуальном режиме.
Проанализируем алгоритм действий:
?().Пример подготовки кода:
// Оригинальный код, который не открывается:
// ТекстЗапроса = "ВЫБРАТЬ... ГДЕ " + ?(Условие, "Поле1", "Поле2");
// Временная строка для конструктора:
ТекстЗапроса = "ВЫБРАТЬ... ГДЕ Поле1";
В старых конфигурациях, таких как УСО 1.2, для реализации гибких фильтров часто применяется объект ПостроительЗапроса. Посмотрим на ситуацию с этой стороны: если вам нужно динамически добавлять условия ГДЕ, лучше не «клеить» строку вручную, а использовать коллекцию Отбор.
Разберем пример: если условие ТолькоБезАктов должно накладываться только в определенном случае, мы можем программно добавить элемент отбора в построитель. Это избавит нас от необходимости писать сложные вложенные условия в самом тексте запроса и позволит конструктору оставаться работоспособным.
Часто при ручной сборке запроса возникают ошибки, которые проявляются только в момент выполнения (Runtime). Рассмотрим основные моменты, на которые стоит обратить внимание:
"ГДЕ "+Условие, если переменная Условие начинается сразу с имени поля, может получиться ГДЕПоле1. Всегда проверяйте наличие пробелов перед и после кавычек.ТолькоБезАктов имеет тип Булево, иначе сравнение в запросе может отработать некорректно.Запрос.Текст в консоль запросов. Это покажет вам финальный результат сборки, где все функции 1С уже выполнены.Мы выяснили, что ошибка в конфигураторе — это не баг платформы, а ограничение инструментария. Конструктор запроса предназначен для работы с языком запросов SQL, а не с кодом 1С. Использование параметров запроса является «золотым стандартом» разработки, так как это не только решает проблему с конструктором, но и повышает производительность системы. Однако для быстрой правки старого кода методы с «заглушками» остаются вполне рабочим инструментом в арсенале программиста 1С.