Запрос падает на первой же строке: разбираем ошибку с ключевым словом ВЫБРАТЬ
Содержание
Ошибка выбора в 1С 8.3 с текстом вида {(1, 1)}: Ожидается выражение "ВЫБРАТЬ" значит одно: парсер языка запросов дошёл до места, где должен начинаться запрос, и не нашёл там ключевого слова ВЫБРАТЬ (или SELECT). Чаще всего виноват не сам запрос, а то, что попало в Запрос.Текст перед вызовом Выполнить(): пустая строка, мусор перед первым словом, пустой элемент пакета или конструкция из чужого диалекта SQL.
Чтобы исправить, посмотрите на реальный текст в момент выполнения, найдите позицию по координатам из сообщения и уберите то, что стоит на месте ВЫБРАТЬ. Если сообщение другое — про права или конфликт блокировок, — это уже не синтаксис, и лечится оно иначе.
Как читать сообщение и почему парсер ждёт ВЫБРАТЬ
Язык запросов 1С строгий: каждый запрос пакета начинается с ВЫБРАТЬ или с УНИЧТОЖИТЬ (для удаления временной таблицы). Вложенный запрос в скобках и каждая часть после ОБЪЕДИНИТЬ тоже начинаются с ВЫБРАТЬ. Если в этих точках стоит что-то другое, платформа сообщает, что ожидала выражение выбора.
Координаты в фигурных скобках — главная подсказка:
- 📍 первое число — номер строки в тексте запроса;
- 📍 второе — номер символа в этой строке;
- 📍
(1, 1)— проблема в самом начале текста: он пустой или начинается не с того слова.
Если координаты указывают на середину текста, ищите там ;, ОБЪЕДИНИТЬ или открывающую скобку подзапроса. Ошибка сидит сразу за ними.
Строки считаются по тексту запроса, а не по строкам модуля. Если текст собран из нескольких переменных, номер строки в модуле и в запросе не совпадёт.
Полное сообщение при вызове из кода обычно выглядит так:
Ошибка при вызове метода контекста (Выполнить)
по причине:
{(1, 1)}: Ожидается выражение "ВЫБРАТЬ"
Синтаксические причины ошибки выбора в тексте запроса
Ниже — источники ошибки, которые встречаются на практике. Проверяйте их сверху вниз: первые три проверяются быстрее всего.
Пустой текст запроса
Самая частая история. Запрос.Текст не заполнили, заполнили в другой ветке условия или перезаписали пустой строкой.
Запрос = Новый Запрос;
Если ЕстьОтбор Тогда
Запрос.Текст = ТекстСОтбором;
КонецЕсли;
// при ЕстьОтбор = Ложь текст пустой
Результат = Запрос.Выполнить();
Тот же эффект даёт функция-конструктор текста, которая по какой-то ветке возвращает "" или Неопределено.
Посторонние символы перед ВЫБРАТЬ
- ✂️ остаток от копирования: точка, кавычка, номер строки из чужого листинга;
- ✂️ символ
|в начале, если текст скопирован из модуля вместе с разметкой многострочной строки и вставлен в консоль; - ✂️ лишняя буква после правки:
ВВЫБРАТЬ,ВЫБРТЬ.
Латиница внутри русского слова
Коварный случай. Буквы В, Р, А в латинской раскладке выглядят так же, как кириллические. Слово ВЫБРАТЬ, набранное с латинской B или P, на экране не отличить, но парсер его не узнает.
Как проверить: перенаберите слово вручную в обычной раскладке. Если ошибка ушла — дело было в смешанных буквах.
Пустой элемент пакета
Пакетный запрос делится на части точкой с запятой. Две ; подряд или ; с пробелами и переносами между ними создают пустую часть, и для неё платформа ждёт ВЫБРАТЬ.
Так бывает при сборке пакета в цикле: условие не сработало, а разделитель всё равно добавили.
После ОБЪЕДИНИТЬ или в скобках подзапроса нет ВЫБРАТЬ
ВЫБРАТЬ Товары.Ссылка ИЗ Справочник.Номенклатура КАК Товары
ОБЪЕДИНИТЬ ВСЕ
// здесь должна быть вторая часть
То же со вложенным запросом: после В ( и после СОЕДИНЕНИЕ ( парсер ждёт ВЫБРАТЬ. Если там стоит имя таблицы без запроса, будет ошибка.
Неправильный порядок ключевых слов
РАЗРЕШЕННЫЕ, РАЗЛИЧНЫЕ, ПЕРВЫЕ N пишутся после ВЫБРАТЬ, а не перед ним. Текст РАЗРЕШЕННЫЕ ВЫБРАТЬ ... даст ошибку уже на первом слове.
Правильно:
ВЫБРАТЬ РАЗРЕШЕННЫЕ ПЕРВЫЕ 10
Контрагенты.Ссылка
ИЗ
Справочник.Контрагенты КАК Контрагенты
Поиск ошибки в Конструкторе запроса и в текстовом режиме
Конструктор запроса — первый инструмент диагностики. Он разбирает текст тем же парсером, что и платформа при выполнении.
- Откройте модуль в Конфигураторе, поставьте курсор внутрь текста запроса.
- Вызовите Конструктор запроса из контекстного меню.
- Если текст некорректен, Конструктор не откроется и покажет сообщение с той же ошибкой и координатами.
- Курсор в модуле встанет рядом с местом ошибки — поправьте текст и повторите.
Для текста, который собирается в коде из кусков, Конструктор бесполезен: он видит только литерал в модуле. Здесь нужен реальный текст в момент выполнения.
Текст из отладчика
- Поставьте точку останова на строке
Запрос.Выполнить(). - Запустите отладку и дойдите до точки.
- Вычислите выражение
Запрос.Текств окне «Вычислить выражение» (Shift+F9). - Скопируйте значение и вставьте его в консоль запросов или в Конструктор.
Пустая строка в результате сразу закрывает вопрос: ошибка в логике заполнения текста, а не в синтаксисе.
Если отладчик недоступен
В рабочей базе отладку включают не всегда. Тогда временно выведите текст в журнал регистрации:
ЗаписьЖурналаРегистрации("Отладка запроса",
УровеньЖурналаРегистрации.Информация, , ,
"Длина: " + Формат(СтрДлина(Запрос.Текст), "ЧН=0; ЧГ=0") + Символы.ПС + Запрос.Текст);
Длина 0 — текст пустой. Длина больше нуля, но запрос «выглядит нормально» — ищите невидимые символы и латиницу.
Запросы к внешним источникам и тексты из других систем
Отдельная группа ошибок появляется, когда текст запроса приходит не из Конструктора, а из интеграции: из файла настроек, от внешней системы, из чужого кода на SQL.
Язык запросов 1С похож на SQL и понимает английские ключевые слова (SELECT, FROM, WHERE), но это не T-SQL и не диалект PostgreSQL. Конструкции, которых в нём нет, ломают разбор на первом слове:
| Что пришло в текст | Почему ошибка | Что сделать |
|---|---|---|
WITH cte AS (...) SELECT ... | общих табличных выражений в языке запросов 1С нет | заменить на временную таблицу ПОМЕСТИТЬ в пакете |
EXEC имя_процедуры | вызов хранимых процедур языком запросов не поддерживается | для внешнего источника — команда источника, для SQL — отдельное подключение |
SELECT TOP 10 ... | TOP в 1С записывается как ПЕРВЫЕ | писать ВЫБРАТЬ ПЕРВЫЕ 10 |
| текст в кавычках или с экранированием JSON | первым символом идёт кавычка или \ | очистить строку перед присвоением |
Объект «Внешние источники данных»
Таблицы внешнего источника запрашиваются тем же языком запросов 1С, через ВнешнийИсточникДанных.ИмяИсточника.Таблица.ИмяТаблицы. Писать туда родной SQL сервера нельзя: платформа сама переводит запрос.
Если текст написан на SQL целевой СУБД, его нужно либо переписать на язык запросов, либо выполнять через отдельное подключение (например, ADO через COM в Windows), где действуют правила самой СУБД.
Текст из файла или макета
При чтении запроса из текстового файла или макета проверьте:
- 📄 не попал ли в начало заголовок или комментарий в чужом формате (
--вместо//); - 📄 не обрезалась ли строка при загрузке;
- 📄 совпадает ли кодировка: при неверной кириллица превращается в набор знаков, и
ВЫБРАТЬперестаёт быть словом.
Комментарии через // язык запросов 1С допускает. Комментарий SQL -- — нет.
Права доступа и блокировки: когда дело не в синтаксисе
Пользователи часто называют «ошибкой выбора» любой сбой запроса. Важно отличать синтаксическую ошибку от проблем с правами и блокировками: у них другие тексты и другое лечение.
| Признак в сообщении | Что это | Куда смотреть |
|---|---|---|
координаты {(строка, колонка)} и «Ожидается…» | синтаксис текста | текст запроса |
| «Недостаточно прав…» | у роли нет права чтения таблицы | роли пользователя |
| «Нарушение прав доступа» | сработало ограничение на уровне записей | ключевое слово РАЗРЕШЕННЫЕ, настройки RLS |
| «Конфликт блокировок при выполнении транзакции» | другой сеанс держит данные | время выполнения, параллельные операции |
Права и РАЗРЕШЕННЫЕ
Если в конфигурации настроено ограничение доступа на уровне записей, запрос без РАЗРЕШЕННЫЕ у пользователя с ограничениями упадёт при попытке прочитать недоступные записи. Добавление слова снимает ошибку: запрос вернёт только разрешённые строки.
Добавлять его нужно строго после ВЫБРАТЬ. Поставили перед — получили как раз ошибку с ожиданием ВЫБРАТЬ. Так одна правка превращает ошибку прав в синтаксическую, и выглядит это как новая проблема.
Блокировки и ДЛЯ ИЗМЕНЕНИЯ
Предложение ДЛЯ ИЗМЕНЕНИЯ пишется в конце запроса и работает в автоматическом режиме управления блокировками. В управляемом режиме, который используют современные типовые конфигурации, данные блокируют объектом БлокировкаДанных, а не через текст запроса.
Конфликт блокировок не связан с синтаксисом. Переписывать текст запроса тут бесполезно — ищите, какая операция в другом сеансе держит те же данные.
Не завершайте чужие сеансы, чтобы «снять блокировку», в рабочее время. У пользователей оборвётся несохранённая работа и откатятся незавершённые транзакции. Если без этого не обойтись — предупредите людей и делайте это вне пиковой нагрузки.
Порядок исправления: от сообщения до рабочего запроса
Общий алгоритм для любого случая:
- Скопируйте полный текст ошибки вместе с координатами.
- Получите реальный текст запроса на момент выполнения — через отладчик или журнал регистрации.
- Вставьте текст в Конструктор запроса или консоль запросов. Если ошибка повторилась — проблема в тексте, если нет — в том, как текст собирается в коде.
- Найдите строку и символ по координатам. Посмотрите, что стоит перед этой позицией:
;,ОБЪЕДИНИТЬ,(. - Исправьте и проверьте запрос в консоли на копии базы или на небольшой выборке через
ПЕРВЫЕ 10. - Верните исправленный текст в модуль и уберите временную запись в журнал регистрации.
Сборка пакета без пустых частей
Если пакет собирается из кусков, не склеивайте его вручную с ; после каждого шага. Соберите массив непустых текстов и соедините их один раз:
Части = Новый Массив;
Части.Добавить(ТекстВременнойТаблицы);
Если НужныОстатки Тогда
Части.Добавить(ТекстОстатков);
КонецЕсли;
Части.Добавить(ТекстИтога);
Запрос.Текст = СтрСоединить(Части, ";" + Символы.ПС);
Пустой части в таком пакете не появится, если каждый добавленный текст сам по себе непустой.
Как не получать ошибку снова
Профилактика сводится к нескольким привычкам разработчика.
- 🧱 Пишите запросы в Конструкторе и правьте их там же: он не пропустит синтаксическую ошибку.
- 🧱 Держите текст запроса целиком в одном месте. Если нужны варианты — используйте параметры и условия внутри запроса (
ГДЕ &ИспользоватьОтбор = ЛОЖЬ ИЛИ ...), а не склейку строк. - 🧱 Перед
Выполнить()в сложных сценариях проверяйтеЗначениеЗаполнено(Запрос.Текст)и выдавайте понятное сообщение. - 🧱 Не копируйте SQL из других систем «как есть». Переписывайте под язык запросов 1С.
- 🧱 Если запрос не открывается в Конструкторе без видимой причины, перенаберите ключевые слова вручную в русской раскладке.
- 🧱 Проверяйте запрос из внешних файлов при загрузке, а не при выполнении: сразу видно, что пришло.