При работе с платформой 1С:Предприятие 7.7 начинающие и даже опытные разработчики часто сталкиваются с ситуацией, когда встроенный язык запросов отказывается распознавать переменную, содержащую СписокЗначений. Несмотря на то, что объект создан и заполнен в коде, при выполнении метода Выполнить() система выдает ошибку: «Переменная не определена». В рамках данной статьи мы подробно разберем причины этой ошибки, проанализируем механизмы работы области видимости в 1С 7.7 и рассмотрим лучшие практики оптимизации запросов.
Рассмотрим типичную ситуацию: разработчик создает объект СписокЗначений, наполняет его элементами справочника и пытается использовать в тексте запроса через оператор Условие. Однако система сообщает, что переменная списка не найдена. Основная причина кроется в том, как парсер запросов 1С 7.7 взаимодействует с контекстом модуля.
Проанализируем ситуацию: если текст запроса формируется в одной функции, а сам объект запроса создается и выполняется в другой, или если переменная списка определена как локальная внутри процедуры, запрос может её «не увидеть». В 1С 7.7 для успешного выполнения условия В необходимо, чтобы переменная, содержащая СписокЗначений, была доступна в том же контексте, где вызывается метод Запрос.Выполнить(ТекстЗапроса).
Для решения этой проблемы мы можем использовать несколько подходов:
Перем МойСписок; в самом верху модуля (модуля формы или модуля документа), она станет доступна всем процедурам и функциям этого модуля, включая внутренние механизмы объекта Запрос.Экспорт.Важно помнить, что синтаксис 1С 7.7 отличается от 1С 8.x. В «семерке» не используется символ амперсанда (&) перед именем параметра в тексте запроса. Посмотрим на правильный пример формирования текста запроса:
МойСписок = СоздатьОбъект("СписокЗначений");
// Заполнение списка...
ТекстЗапроса = "
|Товар = Справочник.Товары.ТекущийЭлемент;
|Условие (Товар В МойСписок);
|";
Если Запрос.Выполнить(ТекстЗапроса) = 1 Тогда
// Обработка результатов
КонецЕсли;
Если вы случайно добавите & перед МойСписок, как это делается в более современных версиях платформы, 1С 7.7 выдаст синтаксическую ошибку.
Разберем важный нюанс производительности, который часто упускают из виду. В сообщениях форума часто встречается использование кодов справочника (строковых или числовых) для фильтрации. Рассмотрим пример кода, который является неоптимальным:
МойСписок.ДобавитьЗначение(МойСправочник.Код);
// ... в запросе
|КодЭлемента = Документ.МойДокумент.Товар.Код;
|Условие (КодЭлемента В МойСписок);
Проанализируем, почему это плохо. Когда вы обращаетесь к Товар.Код в запросе, система вынуждена выполнять соединение (JOIN) таблицы документов с таблицей справочника, чтобы получить строковое значение кода для каждого товара. Если в документе тысячи строк, это существенно замедляет работу.
Правильный подход: использовать ссылки на объекты. Ссылка в 1С 7.7 — это внутренний идентификатор (ID), который хранится непосредственно в таблице документа. Сравнение идентификаторов происходит гораздо быстрее, чем сравнение строк. Рассмотрим правильный способ заполнения списка:
МойСправочник = СоздатьОбъект("Справочник.Товары");
МойСписок = СоздатьОбъект("СписокЗначений");
Если МойСправочник.НайтиПоКоду("284") = 1 Тогда
МойСписок.ДобавитьЗначение(МойСправочник.ТекущийЭлемент());
КонецЕсли;
ТекстЗапроса = "
|Товар = Документ.Реализация.Товар;
|Условие (Товар В МойСписок);
|";
При заполнении списка значений через поиск по коду, как в примере выше, часто возникает ошибка «элемент не найден». Выясним причину. В 1С 7.7 длина кода справочника фиксирована в метаданных. Если длина кода установлена, например, в 10 символов, а вы ищете код "284", поиск может завершиться неудачей, так как реальный код в базе выглядит как "0000000284".
Для корректного поиска рекомендуется использовать дополнение строки нулями или встроенные функции конфигурации (например, глПреобразоватьНомер в типовых решениях). Также всегда проверяйте результат выполнения метода НайтиПоКоду(), прежде чем добавлять значение в список, чтобы избежать попадания пустых значений, которые могут исказить результат запроса.
Если ваша база данных работает на Microsoft SQL Server, следует учитывать еще один технический момент. При использовании условия В СписокЗначений движок 1С 7.7 преобразует это условие в SQL-запрос с оператором IN (...) или серией условий OR.
Если в вашем списке находятся тысячи элементов, результирующий SQL-запрос может стать слишком длинным, что приведет к ошибке переполнения буфера или отказу сервера базы данных. В таких случаях рекомендуется:
Подведем итоги нашего исследования. Для того чтобы успешно использовать условие вхождения в список в запросе 1С 7.7, необходимо:
СписокЗначений объявлена в области видимости модуля (лучше всего как переменная модуля).ТекущийЭлемент()), а не строковые коды или наименования.& перед именами переменных в тексте запроса.Соблюдение этих простых правил позволит вам писать надежный и быстрый код, избегая трудноуловимых ошибок исполнения.