Мы сталкиваемся с весьма необычным и неочевидным поведением системы 1С:Предприятие в конфигурации Управление торговлей 11.5. Простой, на первый взгляд, объединенный запрос, включающий РегистрНакопления.ЗаказыКлиентов, неожиданно завершается ошибкой "Ожидается выражение "ВЫБРАТЬ"". Рассмотрим эту проблему подробнее, выясним ее причины и разберем возможные пути решения.
Суть проблемы заключается в том, что запрос, построенный с использованием оператора ОБЪЕДИНИТЬ ВСЕ, некорректно выполняется или даже не открывается в конструкторе запросов, если РегистрНакопления.ЗаказыКлиентов не является первым источником данных в объединении. Эта ошибка вводит в заблуждение, поскольку синтаксис запроса может быть абсолютно верным.
Изначально, мы имеем объединенный запрос, который пытается получить имена регистров, связанных с определенным регистратором. Вот пример такого запроса, который вызывал проблему:
ВЫБРАТЬ ПЕРВЫЕ 1 "РасчетыСКлиентами" КАК ИмяРегистра
ИЗ РегистрНакопления.РасчетыСКлиентами
ГДЕ Регистратор = &Регистратор
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ ПЕРВЫЕ 1 "РаспределениеЗапасовДвижения" КАК ИмяРегистра
ИЗ РегистрНакопления.РаспределениеЗапасовДвижения
ГДЕ Регистратор = &Регистратор
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ ПЕРВЫЕ 1 "ЗаказыКлиентов" КАК ИмяРегистра
ИЗ РегистрНакопления.ЗаказыКлиентов
ГДЕ Регистратор = &Регистратор
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ ПЕРВЫЕ 1 "СуммыДокументовВВалютахУчета" КАК ИмяРегистра
ИЗ РегистрСведений.СуммыДокументовВВалютахУчета
ГДЕ Регистратор = &Регистратор
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ ПЕРВЫЕ 1 "ТоварыКОтгрузке" КАК ИмяРегистра
ИЗ РегистрНакопления.ТоварыКОтгрузке
ГДЕ Регистратор = &Регистратор
При выполнении этого запроса мы получаем ошибку "Ожидается выражение "ВЫБРАТЬ"". Наиболее удивительным является то, что:
РегистрНакопления.ЗаказыКлиентов, весь объединенный запрос начинает работать.РегистрНакопления.ЗаказыКлиентов на первую позицию в объединении, запрос также начинает работать без ошибок.Давайте посмотрим на минимальные примеры, подтверждающие это странное поведение:
ЗаказыКлиентов не первым):
ВЫБРАТЬ "Пустышка" КАК ИмяРегистра
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ ПЕРВЫЕ 1 "ЗаказыКлиентов"
ИЗ РегистрНакопления.ЗаказыКлиентов КАК ЗаказыКлиентов
ГДЕ ЗаказыКлиентов.Регистратор = &Регистратор
ЗаказыКлиентов первым):
ВЫБРАТЬ ПЕРВЫЕ 1 "ЗаказыКлиентов" КАК Поле1
ИЗ РегистрНакопления.ЗаказыКлиентов КАК ЗаказыКлиентов
ГДЕ ЗаказыКлиентов.Регистратор = &Регистратор
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ "Пустышка"
Это однозначно указывает на специфическую проблему, связанную именно с РегистрНакопления.ЗаказыКлиентов и его положением в запросе.
В ходе поиска решения было предпринято множество шагов, характерных для диагностики неочевидных проблем в 1С:
ВСЕ из оператора ОБЪЕДИНИТЬ ВСЕ.КАК ИмяРегистра из всех подзапросов, кроме первого.ИЗ РегистрНакопления.РаспределениеЗапасовДвижения КАК рег).ЗаказыКлиентов. Список записей регистра открывался без проблем.
Каждый из этих шагов, хотя и не привел к окончательному решению, помогал сузить круг поиска и подтверждал специфичность проблемы.
Дальнейшее расследование показало, что запрос, который мы анализируем, формируется программно внутри функции ПолучитьИспользуемыеРегистры. Давайте посмотрим на код этой функции:
Функция ПолучитьИспользуемыеРегистры(Регистратор, СписокРегистров)
Запрос = Новый Запрос;
Запрос.УстановитьПараметр("Регистратор", Регистратор);
Результат = Новый Массив;
МаксимумТаблицВЗапросе = 256;
СчетчикТаблиц = 0;
ОсталосьРегистров = СписокРегистров.Количество;
ТекстыЗапроса = Новый Массив;
ШаблонЗапроса = "ВЫБРАТЬ ПЕРВЫЕ 1 | ""&ИмяРегистра"" КАК ИмяРегистра |ИЗ | &Таблица |ГДЕ | Регистратор = &Регистратор";
Для каждого Регистр Из СписокРегистров Цикл
ТекстЗапроса = СтрЗаменить(ШаблонЗапроса, "&ИмяРегистра", Регистр.Имя);
ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "&Таблица", Регистр.ПолноеИмя);
ТекстыЗапроса.Добавить(ТекстЗапроса);
СчетчикТаблиц = СчетчикТаблиц + 1;
ОсталосьРегистров = ОсталосьРегистров - 1;
Если СчетчикТаблиц = МаксимумТаблицВЗапросе Или ОсталосьРегистров = 0 И СчетчикТаблиц <> 0 Тогда
Запрос.Текст = СтрСоединить(ТекстыЗапроса, ОбщегоНазначенияУТ.РазделительЗапросовВОбъединении);
СчетчикТаблиц = 0;
ТекстыЗапроса.Очистить;
ОбщегоНазначенияКлиентСервер.ДополнитьМассив(Результат, Запрос.Выполнить.Выгрузить.ВыгрузитьКолонку("ИмяРегистра"));
КонецЕсли;
КонецЦикла;
Возврат Результат;
КонецФункции
Эта функция динамически генерирует текст запроса, объединяя подзапросы для каждого регистра из переданного списка. Ошибка "Ожидается выражение "ВЫБРАТЬ"" возникает именно на строке Запрос.Выполнить.Выгрузить.ВыгрузитьКолонку("ИмяРегистра"), подтверждая, что проблема возникает на этапе выполнения запроса.
В ходе дальнейшего исследования мы выяснили следующее:
РегистрНакопления.ЗаказыКлиентов и он не был первым в объединении. Например, в таком фрагменте запроса:
ВЫБРАТЬ
Таблица.ЗаказКлиента КАК ЗаказКлиента,
Таблица.Номенклатура КАК Номенклатура,
Таблица.Характеристика КАК Характеристика,
Таблица.Серия КАК Серия,
Таблица.КодСтроки КАК КодСтроки,
Таблица.Склад КАК Склад,
Таблица.ЗаказаноПередЗаписью КАК ЗаказаноИзменение,
Таблица.КОформлениюПередЗаписью КАК КОформлениюИзменение,
Таблица.СуммаПередЗаписью КАК СуммаИзменение
ИЗ
ДвиженияЗаказыКлиентовПередЗаписью КАК Таблица
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ
Таблица.ЗаказКлиента КАК ЗаказКлиента,
Таблица.Номенклатура КАК Номенклатура,
Таблица.Характеристика КАК Характеристика,
Таблица.Серия КАК Серия,
Таблица.КодСтроки КАК КодСтроки,
Таблица.Склад КАК Склад,
ВЫБОР КОГДА Таблица.ВидДвижения = ЗНАЧЕНИЕ(ВидДвиженияНакопления.Приход) ТОГДА
-Таблица.Заказано
ИНАЧЕ
Таблица.Заказано
КОНЕЦ КАК ЗаказаноПередЗаписью,
ВЫБОР КОГДА Таблица.ВидДвижения = ЗНАЧЕНИЕ(ВидДвиженияНакопления.Приход) ТОГДА
-Таблица.КОформлению
ИНАЧЕ
Таблица.КОформлению
КОНЕЦ КАК КОформлениюПередЗаписью,
ВЫБОР КОГДА Таблица.ВидДвижения = ЗНАЧЕНИЕ(ВидДвиженияНакопления.Приход) ТОГДА
-Таблица.Сумма
ИНАЧЕ
Таблица.Сумма
КОНЕЦ КАК СуммаПередЗаписью
ИЗ
РегистрНакопления.ЗаказыКлиентов КАК Таблица
ГДЕ
Таблица.Регистратор = &Регистратор
ЗаказыКлиентов для добавления движений по нему в другом документе. При обновлении конфигурации УТ с версии 11.4 до 11.5 могли произойти значительные изменения в структуре регистра ЗаказыКлиентов. Например, в УТ 11.5.18.37 РегистрНакопления.ЗаказыКлиентов был заменен на другие регистры (РаспоряженияНаОтгрузку, РаспоряженияНаОтгрузкуКВыполнению). Если расширение, заимствующее этот регистр, не было своевременно адаптировано под новые изменения, это могло привести к некорректной метаинформации о регистре. Платформа 1С, при попытке разобрать запрос, видит несоответствия в структуре метаданных для ЗаказыКлиентов, особенно когда он не является первым, и выдает общую ошибку "Ожидается выражение "ВЫБРАТЬ"", которая в данном случае является лишь индикатором более глубокой проблемы с метаданными.
Такие ситуации часто возникают, когда расширения изменяют структуру хранения данных (доступно с платформы 8.3.12 и выше). Отключение расширения на время обновления, а затем его некорректная адаптация или устаревшая метаинформация в нем, могут привести к сбоям в работе запросов к заимствованным или измененным регистрам.
Для решения данной проблемы мы можем рассмотреть как краткосрочные обходные пути, так и комплексные долгосрочные решения.
Как мы уже выяснили, запрос начинает работать, если РегистрНакопления.ЗаказыКлиентов всегда располагается первым в объединении. Это можно реализовать программно, изменяя порядок следования регистров в списке перед формированием запроса. Например, в функции ПолучитьИспользуемыеРегистры можно добавить "костыль" для обеспечения этого порядка:
СписокРегистров, найдите элемент, соответствующий РегистрНакопления.ЗаказыКлиентов.Важно: Это лишь временное решение, которое не устраняет коренную причину проблемы и может привести к новым ошибкам в других местах системы.
Это самый важный шаг. Необходимо детально проанализировать расширение, которое заимствовало РегистрНакопления.ЗаказыКлиентов. Если расширение было отключено во время обновления, его необходимо адаптировать под новую версию конфигурации УТ 11.5. Проверьте:
Если в расширении регистр был заимствован с целью добавления движений в другом документе, убедитесь, что все связи и методы работы с этим регистром в расширении соответствуют текущей логике УТ 11.5. В некоторых случаях может потребоваться не заимствование, а использование стандартных механизмов 1С для работы с данными или создание нового регистра в расширении вместо модификации стандартного.
Запустите процедуру Тестирование и исправление для вашей базы данных. Этот инструмент может помочь устранить возможные логические ошибки, нарушения ссылочной целостности и исправить метаданные, которые могли быть повреждены в процессе обновления или из-за конфликтов с расширениями. Рекомендуется выполнять ТиИ с остановленным сервером 1С, если это возможно, и обязательно сделать резервную копию базы перед началом.
Убедитесь, что вы используете достаточно свежую и стабильную версию платформы 1С:Предприятие 8.3 (указана 8.3.18.1741). Иногда подобные неочевидные ошибки могут быть связаны с ошибками в самой платформе, которые исправляются в более поздних релизах. Рассмотрите возможность обновления платформы до последней рекомендованной версии.
Эта ошибка, на самом деле, часто является общим индикатором того, что 1С не может корректно разобрать синтаксическую структуру запроса. Причины могут быть не в самом синтаксисе, а в некорректной метаинформации о таблицах, на которые ссылается запрос. Когда платформа пытается построить план запроса, она обращается к метаданным о регистрах. Если эти метаданные "испорчены" или не соответствуют друг другу (например, в основной конфигурации и в расширении), возникает сбой на этапе парсинга, который проявляется как "Ожидается выражение "ВЫБРАТЬ"". Размещение проблемной таблицы на первом месте в запросе может изменять порядок обработки метаданных, позволяя платформе обойти ошибку, но не устраняя ее коренную причину.
В заключение, подобные неочевидные ошибки требуют системного подхода к диагностике. Мы должны учитывать все особенности нашего окружения: текущую конфигурацию, версию платформы, наличие и состояние расширений, а также историю обновлений. Сосредоточив усилия на адаптации расширения и проверке целостности метаданных, мы сможем добиться стабильной работы запросов и всей системы в целом.