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