Каждый разработчик на платформе «1С:Предприятие» рано или поздно сталкивается с системным сообщением: «{(1, 1)}: Ожидается выражение "ВЫБРАТЬ"» (или аналогичным англоязычным вариантом Expected expression "SELECT"). Эта ошибка относится к классическим проблемам встроенного синтаксического анализатора (парсера) запросов 1С. Она возникает в тех случаях, когда платформа ожидает получить валидный текст запроса, но вместо этого на вход парсера поступает пустая строка, некорректный тип данных или поврежденный синтаксис.
Особенно часто, как справедливо отмечают практикующие разработчики на форумах, этот сбой проявляется при работе в тонком клиенте и использовании конструктора запросов для управляемых форм и динамических списков. В этой статье мы подробно проанализируем причины возникновения этой ошибки и разберем по шагам практические методы её устранения.
Рассмотрим ситуацию, когда мы используем внешнюю обработку «Консоль запросов» для управляемых форм. Пытаясь создать новый запрос с нуля, мы нажимаем кнопку «Конструктор», но вместо привычного интерфейса получаем ошибку ожидания выражения ВЫБРАТЬ. Выясним причину этого поведения.
При вызове конструктора программный код консоли обычно пытается выполнить стандартный метод инициализации:
Конструктор = Новый КонструкторЗапроса(ТекстЗапросаВФорме);
Если поле ввода на форме абсолютно пустое, переменная ТекстЗапросаВФорме содержит пустую строку "". Платформа пытается распарсить эту строку как готовый запрос. Поскольку правила синтаксиса 1С требуют, чтобы любой запрос начинался с ключевого слова ВЫБРАТЬ (или ВЫБРАТЬ... ИЗ...), анализатор не находит этого слова и блокирует открытие конструктора, выдавая ошибку.
Как решить эту проблему:
Перед тем как нажать кнопку вызова конструктора запросов, напишите в текстовом поле консоли простейший шаблон:
ВЫБРАТЬ 1
После этого конструктор успешно инициализируется, распознает числовую константу и откроет визуальный редактор таблиц. Внутри конструктора вы сможете удалить эту «единицу» и составить нужный вам запрос с нуля. Если вы сами разрабатываете или дорабатываете консоль запросов, мы рекомендуем внедрить автоматический обход этой особенности в коде вызова:
Если СокращенноЛП(ТекстЗапросаВФорме) = "" Тогда
ТекстЗапросаВФорме = "ВЫБРАТЬ 1";
КонецЕсли;
Конструктор = Новый КонструкторЗапроса(ТекстЗапросаВФорме);
Часто ошибка возникает непосредственно во время написания кода модуля в конфигураторе. Мы устанавливаем курсор на строку с текстом запроса, нажимаем правую кнопку мыши и выбираем пункт «Конструктор запроса...».
Проанализируем, почему в этот момент может произойти сбой. Если в процессе работы с кодом вы случайно выделили мышью даже один лишний символ (например, закрывающую скобку, пробел, запятую или кусок комментария) рядом с переменной запроса, конфигуратор попытается передать в конструктор именно этот выделенный некорректный фрагмент. Парсер моментально вернет ошибку ожидания выражения ВЫБРАТЬ.
Решение: всегда проверяйте, чтобы перед вызовом конструктора в текстовом редакторе конфигуратора не было выделено никаких лишних фрагментов. Просто снимите выделение, кликнув в пустую область строки, и только затем вызывайте конструктор.
Отдельного внимания заслуживает работа с динамическими списками в управляемых формах. Разработчики часто сталкиваются со сбоем парсера, когда пытаются динамически «на лету» модифицировать текст запроса списка.
Например, при изменении какого-либо фильтра на форме мы перестраиваем текст запроса динамического списка:
&НаСервере
Процедура ПриИзмененииОтбораНаСервере()
// Опасный способ изменения запроса
Текст = "ВЫБРАТЬ * ИЗ Справочник.Номенклатура ГДЕ Ссылка В (&МассивНоменклатуры)";
Список.ТекстЗапроса = Текст;
КонецПроцедуры
Если в процессе формирования переменной Текст из-за сложного условия или ошибки в коде запишется пустая строка или некорректный синтаксис (например, забыли символ закрытия кавычки или перенос строки), то при попытке отобразить данные на клиенте платформа выдаст ошибку «Ожидается выражение "ВЫБРАТЬ"» и может аварийно завершить работу всего сеанса пользователя.
Как правильно поступать в таких случаях:
// Вместо изменения текста запроса используйте параметры
Список.Параметры.УстановитьЗначениеПараметра("ИспользоватьОтбор", Истина);
Список.Параметры.УстановитьЗначениеПараметра("МассивНоменклатуры", ПолучитьМассивДанных());
Как отмечают участники технических форумов 1С, в тонком клиенте конструктор запросов в режиме «1С:Предприятие» подвержен специфическим сбоям. Особенно остро это проявляется, когда в информационной базе активно используются расширения конфигурации.
Разберем внутреннюю механику этого сбоя. Когда пользователь открывает конструктор запросов в тонком клиенте и пытается выбрать таблицу, тонкий клиент отправляет запрос на сервер для получения актуальной схемы метаданных. Если в базе установлены расширения, которые добавляют новые реквизиты, изменяют типы данных существующих полей или добавляют новые объекты, логика сериализации метаданных между сервером и тонким клиентом может нарушиться.
Тонкий клиент получает от сервера некорректно сформированное или поврежденное описание структуры данных. При попытке отобразить дерево таблиц конструктор "затыкается" на поврежденном узле, не может прочитать схему и падает с ошибкой «Ожидается выражение "ВЫБРАТЬ"», полностью блокируя дальнейшую работу.
Методы обхода проблемы с расширениями:
При использовании устаревших, но до сих пор популярных механизмов ПостроительЗапроса или ПостроительОтчета разработчики нередко совершают типичную ошибку при передаче параметров. Посмотрим на следующий пример кода:
// ОШИБОЧНЫЙ КОД
Запрос = Новый Запрос("ВЫБРАТЬ Ссылка ИЗ Справочник.Контрагенты");
Построитель = Новый ПостроительОтчета;
Построитель.ИсточникДанных = Новый ОписаниеИсточникаДанных(Запрос.Выполнить());
В данном случае разработчик ошибочно пытается передать в источник данных результат выполнения запроса вместо самого объекта Запрос. Построитель пытается интерпретировать переданные данные как структуру описания метаданных запроса, не находит в них текстового тела, начинающегося со слова ВЫБРАТЬ, и возвращает анализируемую нами ошибку.
Правильный вариант работы с построителем:
// ПРАВИЛЬНЫЙ КОД
Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ Ссылка ИЗ Справочник.Контрагенты";
Построитель = Новый ПостроительОтчета;
Построитель.ИсточникДанных = Новый ОписаниеИсточникаДанных(Запрос); // Передаем сам объект Запрос!
Иногда синтаксическая ошибка возникает еще на этапе компиляции модуля в Конфигураторе, когда мы пишем текст запроса вручную на нескольких строках. Проанализируем типичную синтаксическую ошибку форматирования:
// Код, который вызовет ошибку компиляции
Запрос.Текст = "ВЫБРАТЬ
| Ссылка
ИЗ
| Справочник.Номенклатура";
Обратите внимание на слово ИЗ. Если при переносе строк была пропущена вертикальная черта | (обозначающая продолжение многострочного строкового литерала в 1С) или кавычка, синтаксический анализатор воспримет слово ИЗ как команду встроенного языка, а не часть строки запроса. Это приведет к нарушению всей структуры строки запроса, и компилятор выдаст ошибку ожидания выражения ВЫБРАТЬ.
Правильное оформление многострочного запроса:
Запрос.Текст =
"ВЫБРАТЬ
| Номенклатура.Ссылка КАК Ссылка,
| Номенклатура.Код КАК Код
|ИЗ
| Справочник.Номенклатура КАК Номенклатура";
Каждая последующая строка многострочного литерала обязательно должна начинаться с символа вертикальной черты |, а весь блок текста должен находиться внутри двойных кавычек.
Мы подробно разобрали природу ошибки «Ожидается выражение "ВЫБРАТЬ"» в 1С. Чтобы быстро локализовать и устранить этот сбой, придерживайтесь простого алгоритма самопроверки:
ВЫБРАТЬ 1).