Запрос падает на первой же строке: разбираем ошибку с ключевым словом ВЫБРАТЬ

· 10 мин

Содержание

Ошибка выбора в 1С 8.3 с текстом вида {(1, 1)}: Ожидается выражение "ВЫБРАТЬ" значит одно: парсер языка запросов дошёл до места, где должен начинаться запрос, и не нашёл там ключевого слова ВЫБРАТЬ (или SELECT). Чаще всего виноват не сам запрос, а то, что попало в Запрос.Текст перед вызовом Выполнить(): пустая строка, мусор перед первым словом, пустой элемент пакета или конструкция из чужого диалекта SQL.

Чтобы исправить, посмотрите на реальный текст в момент выполнения, найдите позицию по координатам из сообщения и уберите то, что стоит на месте ВЫБРАТЬ. Если сообщение другое — про права или конфликт блокировок, — это уже не синтаксис, и лечится оно иначе.

Как читать сообщение и почему парсер ждёт ВЫБРАТЬ

Язык запросов 1С строгий: каждый запрос пакета начинается с ВЫБРАТЬ или с УНИЧТОЖИТЬ (для удаления временной таблицы). Вложенный запрос в скобках и каждая часть после ОБЪЕДИНИТЬ тоже начинаются с ВЫБРАТЬ. Если в этих точках стоит что-то другое, платформа сообщает, что ожидала выражение выбора.

Координаты в фигурных скобках — главная подсказка:

  • 📍 первое число — номер строки в тексте запроса;
  • 📍 второе — номер символа в этой строке;
  • 📍 (1, 1) — проблема в самом начале текста: он пустой или начинается не с того слова.

Если координаты указывают на середину текста, ищите там ;, ОБЪЕДИНИТЬ или открывающую скобку подзапроса. Ошибка сидит сразу за ними.

Строки считаются по тексту запроса, а не по строкам модуля. Если текст собран из нескольких переменных, номер строки в модуле и в запросе не совпадёт.

Полное сообщение при вызове из кода обычно выглядит так:

Ошибка при вызове метода контекста (Выполнить)
по причине:
{(1, 1)}: Ожидается выражение "ВЫБРАТЬ"

Синтаксические причины ошибки выбора в тексте запроса

Ниже — источники ошибки, которые встречаются на практике. Проверяйте их сверху вниз: первые три проверяются быстрее всего.

Пустой текст запроса

Самая частая история. Запрос.Текст не заполнили, заполнили в другой ветке условия или перезаписали пустой строкой.

Запрос = Новый Запрос;
Если ЕстьОтбор Тогда
	Запрос.Текст = ТекстСОтбором;
КонецЕсли;
// при ЕстьОтбор = Ложь текст пустой
Результат = Запрос.Выполнить();

Тот же эффект даёт функция-конструктор текста, которая по какой-то ветке возвращает "" или Неопределено.

Посторонние символы перед ВЫБРАТЬ

  • ✂️ остаток от копирования: точка, кавычка, номер строки из чужого листинга;
  • ✂️ символ | в начале, если текст скопирован из модуля вместе с разметкой многострочной строки и вставлен в консоль;
  • ✂️ лишняя буква после правки: ВВЫБРАТЬ, ВЫБРТЬ.

Латиница внутри русского слова

Коварный случай. Буквы В, Р, А в латинской раскладке выглядят так же, как кириллические. Слово ВЫБРАТЬ, набранное с латинской B или P, на экране не отличить, но парсер его не узнает.

Как проверить: перенаберите слово вручную в обычной раскладке. Если ошибка ушла — дело было в смешанных буквах.

Пустой элемент пакета

Пакетный запрос делится на части точкой с запятой. Две ; подряд или ; с пробелами и переносами между ними создают пустую часть, и для неё платформа ждёт ВЫБРАТЬ.

Так бывает при сборке пакета в цикле: условие не сработало, а разделитель всё равно добавили.

После ОБЪЕДИНИТЬ или в скобках подзапроса нет ВЫБРАТЬ

ВЫБРАТЬ Товары.Ссылка ИЗ Справочник.Номенклатура КАК Товары
ОБЪЕДИНИТЬ ВСЕ
// здесь должна быть вторая часть

То же со вложенным запросом: после В ( и после СОЕДИНЕНИЕ ( парсер ждёт ВЫБРАТЬ. Если там стоит имя таблицы без запроса, будет ошибка.

Неправильный порядок ключевых слов

РАЗРЕШЕННЫЕ, РАЗЛИЧНЫЕ, ПЕРВЫЕ N пишутся после ВЫБРАТЬ, а не перед ним. Текст РАЗРЕШЕННЫЕ ВЫБРАТЬ ... даст ошибку уже на первом слове.

Правильно:

ВЫБРАТЬ РАЗРЕШЕННЫЕ ПЕРВЫЕ 10
	Контрагенты.Ссылка
ИЗ
	Справочник.Контрагенты КАК Контрагенты

Поиск ошибки в Конструкторе запроса и в текстовом режиме

Конструктор запроса — первый инструмент диагностики. Он разбирает текст тем же парсером, что и платформа при выполнении.

  1. Откройте модуль в Конфигураторе, поставьте курсор внутрь текста запроса.
  2. Вызовите Конструктор запроса из контекстного меню.
  3. Если текст некорректен, Конструктор не откроется и покажет сообщение с той же ошибкой и координатами.
  4. Курсор в модуле встанет рядом с местом ошибки — поправьте текст и повторите.

Для текста, который собирается в коде из кусков, Конструктор бесполезен: он видит только литерал в модуле. Здесь нужен реальный текст в момент выполнения.

Текст из отладчика

  1. Поставьте точку останова на строке Запрос.Выполнить().
  2. Запустите отладку и дойдите до точки.
  3. Вычислите выражение Запрос.Текст в окне «Вычислить выражение» (Shift+F9).
  4. Скопируйте значение и вставьте его в консоль запросов или в Конструктор.

Пустая строка в результате сразу закрывает вопрос: ошибка в логике заполнения текста, а не в синтаксисе.

Если отладчик недоступен

В рабочей базе отладку включают не всегда. Тогда временно выведите текст в журнал регистрации:

ЗаписьЖурналаРегистрации("Отладка запроса",
	УровеньЖурналаРегистрации.Информация, , ,
	"Длина: " + Формат(СтрДлина(Запрос.Текст), "ЧН=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
«Конфликт блокировок при выполнении транзакции»другой сеанс держит данныевремя выполнения, параллельные операции

Права и РАЗРЕШЕННЫЕ

Если в конфигурации настроено ограничение доступа на уровне записей, запрос без РАЗРЕШЕННЫЕ у пользователя с ограничениями упадёт при попытке прочитать недоступные записи. Добавление слова снимает ошибку: запрос вернёт только разрешённые строки.

Добавлять его нужно строго после ВЫБРАТЬ. Поставили перед — получили как раз ошибку с ожиданием ВЫБРАТЬ. Так одна правка превращает ошибку прав в синтаксическую, и выглядит это как новая проблема.

Блокировки и ДЛЯ ИЗМЕНЕНИЯ

Предложение ДЛЯ ИЗМЕНЕНИЯ пишется в конце запроса и работает в автоматическом режиме управления блокировками. В управляемом режиме, который используют современные типовые конфигурации, данные блокируют объектом БлокировкаДанных, а не через текст запроса.

Конфликт блокировок не связан с синтаксисом. Переписывать текст запроса тут бесполезно — ищите, какая операция в другом сеансе держит те же данные.

Не завершайте чужие сеансы, чтобы «снять блокировку», в рабочее время. У пользователей оборвётся несохранённая работа и откатятся незавершённые транзакции. Если без этого не обойтись — предупредите людей и делайте это вне пиковой нагрузки.

Порядок исправления: от сообщения до рабочего запроса

Диагностика: выберите симптом

Общий алгоритм для любого случая:

  1. Скопируйте полный текст ошибки вместе с координатами.
  2. Получите реальный текст запроса на момент выполнения — через отладчик или журнал регистрации.
  3. Вставьте текст в Конструктор запроса или консоль запросов. Если ошибка повторилась — проблема в тексте, если нет — в том, как текст собирается в коде.
  4. Найдите строку и символ по координатам. Посмотрите, что стоит перед этой позицией: ;, ОБЪЕДИНИТЬ, (.
  5. Исправьте и проверьте запрос в консоли на копии базы или на небольшой выборке через ПЕРВЫЕ 10.
  6. Верните исправленный текст в модуль и уберите временную запись в журнал регистрации.

Сборка пакета без пустых частей

Если пакет собирается из кусков, не склеивайте его вручную с ; после каждого шага. Соберите массив непустых текстов и соедините их один раз:

Части = Новый Массив;
Части.Добавить(ТекстВременнойТаблицы);
Если НужныОстатки Тогда
	Части.Добавить(ТекстОстатков);
КонецЕсли;
Части.Добавить(ТекстИтога);

Запрос.Текст = СтрСоединить(Части, ";" + Символы.ПС);

Пустой части в таком пакете не появится, если каждый добавленный текст сам по себе непустой.

Как не получать ошибку снова

Профилактика сводится к нескольким привычкам разработчика.

  • 🧱 Пишите запросы в Конструкторе и правьте их там же: он не пропустит синтаксическую ошибку.
  • 🧱 Держите текст запроса целиком в одном месте. Если нужны варианты — используйте параметры и условия внутри запроса (ГДЕ &ИспользоватьОтбор = ЛОЖЬ ИЛИ ...), а не склейку строк.
  • 🧱 Перед Выполнить() в сложных сценариях проверяйте ЗначениеЗаполнено(Запрос.Текст) и выдавайте понятное сообщение.
  • 🧱 Не копируйте SQL из других систем «как есть». Переписывайте под язык запросов 1С.
  • 🧱 Если запрос не открывается в Конструкторе без видимой причины, перенаберите ключевые слова вручную в русской раскладке.
  • 🧱 Проверяйте запрос из внешних файлов при загрузке, а не при выполнении: сразу видно, что пришло.
Перед выпуском запроса в рабочую базу
Выполнено: 0 / 6

Частые вопросы

Можно ли писать запрос на английском, через SELECT?
Да. Язык запросов 1С понимает английские ключевые слова: SELECT, FROM, WHERE, UNION ALL. Смешивать русские и английские слова в одном запросе тоже можно, но читать такой текст неудобно.
Почему в консоли запрос работает, а в коде падает с ожиданием ВЫБРАТЬ?
В консоль вы вставили готовый текст, а в коде он собирается иначе: из переменных, по условиям, из макета. Сравните текст из отладчика на строке Выполнить() с тем, что проверяли в консоли.
Ошибка появляется только у одного пользователя. Это синтаксис?
Синтаксис не зависит от пользователя. Если ошибка с ожиданием ВЫБРАТЬ возникает выборочно, текст запроса собирается по-разному для разных пользователей: например, ветка по правам или настройкам оставляет его пустым.
Помогает ли от этой ошибки обновление платформы или тестирование базы?
Нет. Ошибка возникает при разборе текста запроса, до обращения к данным. Тестирование и исправление информационной базы, очистка кэша и смена релиза платформы её не лечат.
Откуда ошибка в отчёте СКД, если я не писал код?
В схеме компоновки данных у набора данных типа «Запрос» поле текста может оказаться пустым или испорченным после правки. Откройте схему, выберите набор и запустите для него Конструктор запроса.