К статье
Практический материал

Разработка и Конфигурация · 10 мин

Как работает оператор ИЛИ в 1С

Разбираем логический оператор ИЛИ в 1С: синтаксис в запросах и коде, приоритет операторов, сочетание с И и НЕ, типичные ошибки и способы проверки результата.

Логический оператор ИЛИ в 1С встречается в двух контекстах: во встроенном языке (в конструкциях Если...Тогда) и в языке запросов (в секциях ГДЕ, ИМЕЮЩИЕ, в условиях соединений). В обоих случаях смысл одинаков: условие считается истинным, если истинно хотя бы одно из сравнений. Но синтаксис, приоритет вычислений и поведение с NULL отличаются, и именно здесь чаще всего возникают ошибки.

Типичная ситуация: разработчик пишет условие «ГДЕ Склад = &Склад1 ИЛИ Склад = &Склад2 И Активен», ожидая два активных варианта, а получает выборку, в которую попадают лишние записи. Причина — приоритет операторов: И вычисляется раньше ИЛИ. Понимание этих правил позволяет писать условия, которые работают предсказуемо и не требуют отладки «методом тыка».

Ниже разобран синтаксис ИЛИ в коде и запросах, правила приоритета, работа с NULL, альтернатива через В(...) и способы проверить, что условие отбирает именно то, что задумано.

Синтаксис ИЛИ во встроенном языке 1С

Во встроенном языке оператор пишется как ИЛИ (в английском варианте синтаксиса — OR) и используется в логических выражениях: Если А ИЛИ Б Тогда ... КонецЕсли;. Оба операнда должны иметь тип Булево. Если хотя бы один из них равен Истина, всё выражение возвращает Истина.

Важная особенность встроенного языка — полное вычисление выражения. В отличие от некоторых языков, 1С вычисляет обе части условия, даже если первой достаточно для результата. Поэтому конструкция вида Если ЗначениеЗаполнено(Ссылка) И Ссылка.Проведен Тогда безопасна, а вот вызов метода у потенциально пустого значения во второй части ИЛИ может вызвать ошибку, если первая часть не защищает от этого.

Если Контрагент.ЭтоГруппа ИЛИ Контрагент.ПометкаУдаления Тогда

Продолжить;

КонецЕсли;

Оператор можно комбинировать с И и НЕ в одном выражении. Читаемость при этом быстро падает, поэтому сложные условия лучше выносить в отдельную функцию с говорящим именем или разбивать на несколько проверок.

Оператор ИЛИ в языке запросов

В запросах ИЛИ применяется в секции ГДЕ, в условиях соединения таблиц (ПО ...), в ИМЕЮЩИЕ и внутри конструкции ВЫБОР КОГДА. Синтаксис тот же: ГДЕ Поле1 = &Значение1 ИЛИ Поле2 = &Значение2. Запрос вернёт строки, где выполняется хотя бы одно из условий.

ВЫБРАТЬ

Товары.Ссылка,

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

ИЗ

Справочник.Номенклатура КАК Товары

ГДЕ

Товары.ВидНоменклатуры = &Вид1

ИЛИ Товары.ВидНоменклатуры = &Вид2

Конструктор запроса в конфигураторе позволяет собирать условия мышью, но при группировке И/ИЛИ он не всегда расставляет скобки так, как ожидает разработчик. После редактирования условий в конструкторе полезно переключиться в текст запроса и проверить итоговую структуру вручную.

Приоритет операторов и роль скобок

Порядок вычисления в 1С (и в коде, и в запросах): сначала НЕ, затем И, затем ИЛИ. Это значит, что выражение А И Б ИЛИ В эквивалентно (А И Б) ИЛИ В, а не А И (Б ИЛИ В). Разница в результате может быть принципиальной.

Практическое правило: как только в одном выражении встречаются И и ИЛИ одновременно, расставляйте скобки явно, даже если приоритет формально совпадает с задуманным. Это защищает от ошибок при последующих правках, когда другой разработчик добавит ещё одно условие и не заметит изменения логики.

Как читается условие

А И Б ИЛИ В

Вычисляется как (А И Б) ИЛИ В. Вариант В срабатывает независимо от А.

А И (Б ИЛИ В)

А обязательно, а из Б и В достаточно одного. Логика принципиально другая.

(А ИЛИ Б) И (В ИЛИ Г)

Две независимые группы условий, обе должны быть истинны.

Замена цепочек ИЛИ конструкцией В

Когда ИЛИ сравнивает одно поле с несколькими значениями, цепочку стоит заменить оператором В. Вместо Склад = &С1 ИЛИ Склад = &С2 ИЛИ Склад = &С3 пишется Склад В (&СписокСкладов), где параметр — массив или список значений. Такой запрос короче, легче поддерживается и, как правило, не хуже по производительности.

Дополнительное преимущество — динамичность: количество значений в списке можно менять из кода без переписывания текста запроса. Это стандартный приём для отборов, которые пользователь настраивает через множественный выбор в форме.

bsl
СписокСкладов = Новый Массив;
СписокСкладов.Добавить(Склад1);
СписокСкладов.Добавить(Склад2);
Запрос.УстановитьПараметр("Склады", СписокСкладов);
// В тексте запроса: ГДЕ Продажи.Склад В (&Склады)

Аналог в условиях кода — проверка через массив и метод Найти() или через соответствие, когда значений много и проверка выполняется в цикле.

ИЛИ и значения NULL в запросах

В запросах 1С действует трёхзначная логика: результат сравнения может быть Истина, Ложь или NULL (неопределено), если один из операндов — NULL. Условие Поле = &Значение ИЛИ Поле ЕСТЬ NULL — корректный способ отобрать и совпадающие, и незаполненные значения. А вот Поле = &Значение ИЛИ Поле <> &Значение не вернёт строки с NULL, потому что оба сравнения для NULL дают неопределённость.

NULL чаще всего появляется при левых соединениях, когда в присоединяемой таблице нет подходящей строки. Если условие с ИЛИ накладывается на поле из правой таблицы левого соединения, проверяйте поведение на данных, где связь отсутствует, — иначе часть записей «потеряется» незаметно.

Как проверить, что условие с ИЛИ работает правильно

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

Во встроенном языке сложное условие можно разложить на переменные с промежуточными результатами и посмотреть их в отладчике. Если условие собирается динамически (например, в СКД или через построитель запроса), выведите итоговый текст запроса в журнал или сообщение — часто ошибка видна сразу после того, как условие предстало в собранном виде.

Контрольные точки

Как проверить результат

Скобки в тексте запроса
Норма

Группы И/ИЛИ явно обёрнуты в скобки по задуманной логике

Тревожный признак

Условия идут подряд без скобок, приоритет определяет результат

Записи с NULL
Норма

Незаполненные поля либо явно включены через ЕСТЬ NULL, либо осознанно исключены

Тревожный признак

Часть ожидаемых записей пропала без объяснения

Контрольный пример
Норма

На тестовых данных выборка совпадает с ожидаемым списком

Тревожный признак

В выборку попадают лишние или пропадают нужные записи

Пометка удаления
Норма

Помеченные объекты исключены для всех веток ИЛИ

Тревожный признак

Пометка исключается только для одной ветки условия

Типичные ошибки при использовании ИЛИ

Типичные ошибки
01
Отсутствие скобок при смешивании И и ИЛИ — условие вычисляется не так, как задумано, и в выборку попадают лишние записи.
02
Сравнение с NULL через знак равенства — строки с незаполненными полями молча выпадают из результата.
03
Длинные цепочки «Поле = А ИЛИ Поле = Б ИЛИ Поле = В» вместо В(&Список) — запрос трудно читать и дорабатывать.
04
Исключение пометки удаления только в одной ветке ИЛИ — в отчётах появляются удалённые объекты.
05
Дублирование условий в коде и в запросе с расхождением логики — форма показывает одно, а проведение проверяет другое.

Отдельная группа проблем — производительность. Условия с ИЛИ по разным полям иногда мешают оптимизатору использовать индексы, особенно в больших таблицах. Если запрос с ИЛИ работает медленно, попробуйте вариант с объединением (ОБЪЕДИНИТЬ ВСЕ) двух простых запросов или пересмотрите логику отбора.

Маршрут решения

Как выбрать конструкцию

Сравнивается одно поле с несколькими значениямиИспользуйте В(&Список) с массивом в параметре
Условия затрагивают разные поля и комбинируются И/ИЛИРасставьте скобки явно и проверьте на контрольных данных
В условии участвуют поля из левого соединенияДобавьте обработку NULL через ЕСТЬ NULL или ЕСТЬNULL()
Запрос с ИЛИ выполняется медленно на большой таблицеПопробуйте ОБЪЕДИНИТЬ ВСЕ вместо одного условия с ИЛИ

FAQ

Чем ИЛИ отличается от исключающего ИЛИ в 1С?

Во встроенном языке и языке запросов 1С есть только обычное ИЛИ: результат истинен, когда истинна хотя бы одна часть, включая случай, когда истинны обе. Отдельного оператора «исключающее ИЛИ» нет; при необходимости его моделируют конструкцией вида (А И НЕ Б) ИЛИ (НЕ А И Б).

Можно ли использовать ИЛИ в условии соединения таблиц?

Да, в секции ПО при соединении допустимы составные условия с И и ИЛИ. Учтите, что сложные условия соединения могут заметно замедлить запрос, а при левом соединении добавляют неопределённые значения NULL, которые нужно обрабатывать отдельно.

Почему запрос с ИЛИ не возвращает записи с пустым полем?

Потому что сравнение NULL с любым значением даёт неопределённый результат, а не Истину. Добавьте в условие явную проверку «ИЛИ Поле ЕСТЬ NULL» либо используйте функцию ЕСТЬNULL(Поле, ЗначениеПоУмолчанию) в выражении сравнения.

Вычисляет ли 1С обе части условия, если первая уже истинна?

Во встроенном языке — да, выражение вычисляется полностью. Поэтому во второй части ИЛИ нельзя полагаться на то, что первая часть «отсечёт» опасный случай: обращение к свойству пустого объекта вызовет ошибку независимо от результата первой проверки.

Что быстрее: цепочка ИЛИ или оператор В?

Для одного поля и списка значений разница обычно невелика, но В(&Список) короче, понятнее и удобнее для динамических отборов. Цепочки ИЛИ по разным полям — отдельный случай: там при проблемах со скоростью стоит проверить вариант с ОБЪЕДИНИТЬ ВСЕ.

Как отладить сложное условие с несколькими И и ИЛИ?

Разбейте выражение на переменные-флаги с промежуточными результатами и посмотрите их значения в отладчике. Для запроса временно выведите проверяемые поля в выборку и сравните результат на данных, где правильный ответ известен заранее.

Итог

Что важно запомнить

ИЛИ возвращает истину, если истинно хотя бы одно условие, но приоритет И выше, поэтому сложные выражения всегда группируйте скобками. Для перечисления значений одного поля применяйте В(&Список), а работу с NULL контролируйте через ЕСТЬ NULL. Проверяйте логику на контрольных данных — это быстрее, чем искать пропавшие записи в отчётах.