Почему не срабатывает условие ГДЕ в запросе при использовании переменной?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При работе с запросами в системе 1С:Предприятие 8 начинающие разработчики часто сталкиваются с ситуацией, когда условие ГДЕ (WHERE) отлично работает с жестко прописанным значением (литералом), но перестает возвращать данные, как только вместо значения подставляется переменная. Разберем детально, почему это происходит, какие ошибки в синтаксисе допускаются чаще всего и как правильно передавать значения в запрос, следуя профессиональным стандартам разработки.

Суть проблемы: конкатенация против параметров

Рассмотрим ситуацию, когда у нас есть переменная ЗначениеНомерЗакупки = "123456789";. Разработчик пытается вставить её в текст запроса следующим образом:


Запрос.Текст = "ВЫБРАТЬ ... ГДЕ СпецификацияКонтракта.НомерЗакупки = ""+ЗначениеНомерЗакупки+""";

В данном случае система воспринимает "+ЗначениеНомерЗакупки+" не как команду к объединению строк в языке 1С, а как часть текста самого запроса. В итоге СУБД ищет в базе данных буквально строку, которая начинается на плюс и заканчивается на плюс. Разумеется, совпадений не находится. Выясним причину, почему так происходит, и как этого избежать.

Решение №1: Использование параметров запроса (Рекомендуемый метод)

Использование параметров — это «золотой стандарт» разработки в 1С. Вместо того чтобы пытаться «склеить» текст запроса с данными, мы оставляем в тексте специальный маркер (параметр), который начинается с символа &, а затем передаем значение этого маркера отдельно через метод УстановитьПараметр().

Разберем этот метод по шагам:

  1. В тексте запроса после оператора сравнения пишем имя параметра (например, &НомерЗакупки).
  2. После формирования текста запроса вызываем метод Запрос.УстановитьПараметр("ИмяПараметра", Значение).
  3. Система сама позаботится о типах данных, кавычках и безопасности.

Посмотрим на правильный пример кода:


&НаСервере
Процедура ЗапросКонтракта()
    
    ЗначениеНомерЗакупки = "123456789";
    
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ
        |	СпецификацияКонтракта.СпецификацияКонтрактаНомерЗакупки КАК НомерЗакупки
        |ИЗ
        |	РегистрСведений.СпецификацияКонтракта КАК СпецификацияКонтракта
        |ГДЕ
        |	СпецификацияКонтракта.СпецификацияКонтрактаНомерЗакупки = &ЗначениеНомерЗакупки";
    
    // Передаем значение переменной в параметр запроса
    Запрос.УстановитьПараметр("ЗначениеНомерЗакупки", ЗначениеНомерЗакупки);
    
    РезультатЗапроса = Запрос.Выполнить();
    Выборка = РезультатЗапроса.Выбрать();
    
    Пока Выборка.Следующий() Цикл
        НоваяСтрока = Спецификация.Добавить();
        НоваяСтрока.НомерЗакупки = Выборка.НомерЗакупки;
    КонецЦикла;

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

Преимущества этого метода:

Решение №2: Динамическое формирование текста (Конкатенация)

Иногда возникают задачи, где текст запроса действительно нужно собрать из частей (например, при построении сложного фильтра). Однако здесь важно не запутаться в кавычках. В 1С внутри строкового литерала двойная кавычка "" превращается в одну кавычку ".

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

Запрос.Текст = "... ГДЕ НомерЗакупки = """ + ЗначениеНомерЗакупки + """";

Рассмотрим подробнее, что здесь происходит: первые три кавычки """ означают начало строки и одну кавычку внутри неё. Затем идет закрытие строки 1С, плюс, переменная, плюс и снова кавычки для закрытия значения. Это крайне неудобный и перегруженный синтаксис, который часто ведет к ошибкам.

Почему запрос может не находить данные, даже если код верный?

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

  1. Фиксированная длина строки: Если у ресурса регистра тип Строка имеет свойство «Допустимая длина: Фиксированная», то 1С дополняет значение пробелами до максимума. Например, при длине 20 символов строка "123" превращается в "123 ". В этом случае обычное равенство = не сработает. Рекомендуется использовать функцию СокрЛП() при записи данных или оператор ПОДОБНО в запросе.
  2. Невидимые символы: В строковых значениях могут присутствовать неразрывные пробелы или символы переноса строк, которые визуально не заметны, но делают строки разными для системы.
  3. Типы данных: Убедитесь, что в переменной ЗначениеНомерЗакупки действительно строка, а не число. В 1С запросах сравнение строки с числом всегда дает ложь (Ложь).

Использование оператора ПОДОБНО для поиска

Если вы не уверены в точном соответствии (например, из-за тех же лишних пробелов), можно использовать оператор ПОДОБНО. Рассмотрим пример:


Запрос.Текст = "... ГДЕ СпецификацияКонтракта.НомерЗакупки ПОДОБНО &НомерЗакупки";
// Добавляем спецсимволы % для поиска по вхождению
Запрос.УстановитьПараметр("НомерЗакупки", "%" + СокрЛП(ЗначениеНомерЗакупки) + "%");

Важное замечание по производительности: Использование знака процента % в начале условия (например, "%123") заставляет СУБД сканировать всю таблицу целиком, игнорируя индексы. Если в вашем регистре миллионы записей, такой запрос будет выполняться очень медленно. Старайтесь всегда использовать точное равенство и параметры.

Подведем итоги

Для корректной работы условия ГДЕ с переменными:

Соблюдение этих простых правил сэкономит вам часы отладки и обеспечит стабильную работу вашей конфигурации 1С.

← На главную