Почему объединенный запрос с РегистромНакопления.ЗаказыКлиентов выдает ошибку "Ожидается выражение ВЫБРАТЬ" в 1С:УТ 11.5?

Программист 1С v8.3 (Управляемые формы) 1С:Управление торговлей Управленческий учет Торговля и дистрибуция
← На главную

Мы сталкиваемся с весьма необычным и неочевидным поведением системы 1С:Предприятие в конфигурации Управление торговлей 11.5. Простой, на первый взгляд, объединенный запрос, включающий РегистрНакопления.ЗаказыКлиентов, неожиданно завершается ошибкой "Ожидается выражение "ВЫБРАТЬ"". Рассмотрим эту проблему подробнее, выясним ее причины и разберем возможные пути решения.

Суть проблемы заключается в том, что запрос, построенный с использованием оператора ОБЪЕДИНИТЬ ВСЕ, некорректно выполняется или даже не открывается в конструкторе запросов, если РегистрНакопления.ЗаказыКлиентов не является первым источником данных в объединении. Эта ошибка вводит в заблуждение, поскольку синтаксис запроса может быть абсолютно верным.

Подробный анализ проблемы: Неожиданное поведение запроса

Изначально, мы имеем объединенный запрос, который пытается получить имена регистров, связанных с определенным регистратором. Вот пример такого запроса, который вызывал проблему:


ВЫБРАТЬ ПЕРВЫЕ 1 "РасчетыСКлиентами" КАК ИмяРегистра
ИЗ РегистрНакопления.РасчетыСКлиентами
ГДЕ Регистратор = &Регистратор

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ ПЕРВЫЕ 1 "РаспределениеЗапасовДвижения" КАК ИмяРегистра
ИЗ РегистрНакопления.РаспределениеЗапасовДвижения
ГДЕ Регистратор = &Регистратор

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ ПЕРВЫЕ 1 "ЗаказыКлиентов" КАК ИмяРегистра
ИЗ РегистрНакопления.ЗаказыКлиентов
ГДЕ Регистратор = &Регистратор

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ ПЕРВЫЕ 1 "СуммыДокументовВВалютахУчета" КАК ИмяРегистра
ИЗ РегистрСведений.СуммыДокументовВВалютахУчета
ГДЕ Регистратор = &Регистратор

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ ПЕРВЫЕ 1 "ТоварыКОтгрузке" КАК ИмяРегистра
ИЗ РегистрНакопления.ТоварыКОтгрузке
ГДЕ Регистратор = &Регистратор

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

  1. Если удалить запрос к таблице РегистрНакопления.ЗаказыКлиентов, весь объединенный запрос начинает работать.
  2. Если переместить запрос к РегистрНакопления.ЗаказыКлиентов на первую позицию в объединении, запрос также начинает работать без ошибок.

Давайте посмотрим на минимальные примеры, подтверждающие это странное поведение:

Нерабочий запрос (ЗаказыКлиентов не первым):


ВЫБРАТЬ "Пустышка" КАК ИмяРегистра
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ ПЕРВЫЕ 1 "ЗаказыКлиентов"
ИЗ РегистрНакопления.ЗаказыКлиентов КАК ЗаказыКлиентов
ГДЕ ЗаказыКлиентов.Регистратор = &Регистратор

Рабочий запрос (ЗаказыКлиентов первым):


ВЫБРАТЬ ПЕРВЫЕ 1 "ЗаказыКлиентов" КАК Поле1
ИЗ РегистрНакопления.ЗаказыКлиентов КАК ЗаказыКлиентов
ГДЕ ЗаказыКлиентов.Регистратор = &Регистратор
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ "Пустышка"

Это однозначно указывает на специфическую проблему, связанную именно с РегистрНакопления.ЗаказыКлиентов и его положением в запросе.

Методы диагностики и "пляски с бубном", которые не помогли (или помогли временно)

В ходе поиска решения было предпринято множество шагов, характерных для диагностики неочевидных проблем в 1С:

  1. Очистка кэша: Мы неоднократно чистили кэш как на клиентской, так и на серверной стороне. Для клиент-серверного режима это означает не просто переподключение базы, а остановку службы сервера 1С и удаление файлов кэша из соответствующих папок по идентификатору базы. К сожалению, этот шаг не привел к долгосрочному решению проблемы, хотя часто помогает при других видах ошибок.
  2. Проверка на непечатные символы: Была сделана попытка скопировать текст запроса в блокнот, а затем обратно в 1С, чтобы исключить наличие скрытых или непечатаемых символов, которые могут вызывать синтаксические ошибки. Это предположение также не подтвердилось.
  3. Изменения синтаксиса запроса:
    • Убирали ключевое слово ВСЕ из оператора ОБЪЕДИНИТЬ ВСЕ.
    • Убирали псевдоним КАК ИмяРегистра из всех подзапросов, кроме первого.
    • Добавляли явные псевдонимы ко всем регистрам (например, ИЗ РегистрНакопления.РаспределениеЗапасовДвижения КАК рег).
    Все эти синтаксические модификации не принесли желаемого результата, подтверждая, что проблема лежит глубже, чем в явных синтаксических неточностях.
  4. Попытка открыть запрос в конструкторе: Конструктор запроса также выдавал ошибку "Ожидается выражение "ВЫБРАТЬ"". Это важный диагностический признак, так как он указывает на то, что сама платформа не может разобрать синтаксическую структуру запроса, а не только выполнить его. Мы знаем, что такая ошибка часто возникает при попытке открыть пустой текст запроса или при выделении только части запроса, но здесь она появлялась при полноценном, хоть и проблемном, тексте.
  5. Проверка прав доступа: Мы убедились, что у пользователя, под которым выполнялся запрос, есть все необходимые права на чтение и работу с регистром ЗаказыКлиентов. Список записей регистра открывался без проблем.

Каждый из этих шагов, хотя и не привел к окончательному решению, помогал сузить круг поиска и подтверждал специфичность проблемы.

Выявление истинного виновника: РегистрНакопления.ЗаказыКлиентов и расширение

Дальнейшее расследование показало, что запрос, который мы анализируем, формируется программно внутри функции ПолучитьИспользуемыеРегистры. Давайте посмотрим на код этой функции:


Функция ПолучитьИспользуемыеРегистры(Регистратор, СписокРегистров)

    Запрос = Новый Запрос;
    Запрос.УстановитьПараметр("Регистратор", Регистратор);

    Результат = Новый Массив;
    МаксимумТаблицВЗапросе = 256;
    СчетчикТаблиц = 0;
    ОсталосьРегистров = СписокРегистров.Количество;
    ТекстыЗапроса = Новый Массив;

    ШаблонЗапроса = "ВЫБРАТЬ ПЕРВЫЕ 1 | ""&ИмяРегистра"" КАК ИмяРегистра |ИЗ | &Таблица |ГДЕ | Регистратор = &Регистратор";

    Для каждого Регистр Из СписокРегистров Цикл
        ТекстЗапроса = СтрЗаменить(ШаблонЗапроса, "&ИмяРегистра", Регистр.Имя);
        ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "&Таблица", Регистр.ПолноеИмя);
        ТекстыЗапроса.Добавить(ТекстЗапроса);

        СчетчикТаблиц = СчетчикТаблиц + 1;
        ОсталосьРегистров = ОсталосьРегистров - 1;

        Если СчетчикТаблиц = МаксимумТаблицВЗапросе Или ОсталосьРегистров = 0 И СчетчикТаблиц <> 0 Тогда
            Запрос.Текст = СтрСоединить(ТекстыЗапроса, ОбщегоНазначенияУТ.РазделительЗапросовВОбъединении);
            СчетчикТаблиц = 0;
            ТекстыЗапроса.Очистить;
            ОбщегоНазначенияКлиентСервер.ДополнитьМассив(Результат, Запрос.Выполнить.Выгрузить.ВыгрузитьКолонку("ИмяРегистра"));
        КонецЕсли;
    КонецЦикла;

    Возврат Результат;

КонецФункции

Эта функция динамически генерирует текст запроса, объединяя подзапросы для каждого регистра из переданного списка. Ошибка "Ожидается выражение "ВЫБРАТЬ"" возникает именно на строке Запрос.Выполнить.Выгрузить.ВыгрузитьКолонку("ИмяРегистра"), подтверждая, что проблема возникает на этапе выполнения запроса.

Ключевое наблюдение и роль расширения

В ходе дальнейшего исследования мы выяснили следующее:

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

Такие ситуации часто возникают, когда расширения изменяют структуру хранения данных (доступно с платформы 8.3.12 и выше). Отключение расширения на время обновления, а затем его некорректная адаптация или устаревшая метаинформация в нем, могут привести к сбоям в работе запросов к заимствованным или измененным регистрам.

Решение проблемы и рекомендации

Для решения данной проблемы мы можем рассмотреть как краткосрочные обходные пути, так и комплексные долгосрочные решения.

Обходной путь (краткосрочное решение):

Как мы уже выяснили, запрос начинает работать, если РегистрНакопления.ЗаказыКлиентов всегда располагается первым в объединении. Это можно реализовать программно, изменяя порядок следования регистров в списке перед формированием запроса. Например, в функции ПолучитьИспользуемыеРегистры можно добавить "костыль" для обеспечения этого порядка:

  1. Перед циклом по СписокРегистров, найдите элемент, соответствующий РегистрНакопления.ЗаказыКлиентов.
  2. Удалите его из текущей позиции.
  3. Вставьте его в начало списка.

Важно: Это лишь временное решение, которое не устраняет коренную причину проблемы и может привести к новым ошибкам в других местах системы.

Комплексное решение:

  1. Анализ и адаптация расширения:

    Это самый важный шаг. Необходимо детально проанализировать расширение, которое заимствовало РегистрНакопления.ЗаказыКлиентов. Если расширение было отключено во время обновления, его необходимо адаптировать под новую версию конфигурации УТ 11.5. Проверьте:

    • Совместимость структуры регистра в расширении с текущей структурой в основной конфигурации.
    • Корректность всех заимствованных объектов и их соответствие текущей версии конфигурации.
    • Возможно, потребуется полное переписывание части расширения, связанной с этим регистром, если его структура в УТ 11.5 сильно изменилась.

    Если в расширении регистр был заимствован с целью добавления движений в другом документе, убедитесь, что все связи и методы работы с этим регистром в расширении соответствуют текущей логике УТ 11.5. В некоторых случаях может потребоваться не заимствование, а использование стандартных механизмов 1С для работы с данными или создание нового регистра в расширении вместо модификации стандартного.

  2. Тестирование и исправление (ТиИ) базы данных:

    Запустите процедуру Тестирование и исправление для вашей базы данных. Этот инструмент может помочь устранить возможные логические ошибки, нарушения ссылочной целостности и исправить метаданные, которые могли быть повреждены в процессе обновления или из-за конфликтов с расширениями. Рекомендуется выполнять ТиИ с остановленным сервером 1С, если это возможно, и обязательно сделать резервную копию базы перед началом.

  3. Проверка версии платформы:

    Убедитесь, что вы используете достаточно свежую и стабильную версию платформы 1С:Предприятие 8.3 (указана 8.3.18.1741). Иногда подобные неочевидные ошибки могут быть связаны с ошибками в самой платформе, которые исправляются в более поздних релизах. Рассмотрите возможность обновления платформы до последней рекомендованной версии.

  4. Почему ошибка "Ожидается выражение ВЫБРАТЬ" вводит в заблуждение:

    Эта ошибка, на самом деле, часто является общим индикатором того, что 1С не может корректно разобрать синтаксическую структуру запроса. Причины могут быть не в самом синтаксисе, а в некорректной метаинформации о таблицах, на которые ссылается запрос. Когда платформа пытается построить план запроса, она обращается к метаданным о регистрах. Если эти метаданные "испорчены" или не соответствуют друг другу (например, в основной конфигурации и в расширении), возникает сбой на этапе парсинга, который проявляется как "Ожидается выражение "ВЫБРАТЬ"". Размещение проблемной таблицы на первом месте в запросе может изменять порядок обработки метаданных, позволяя платформе обойти ошибку, но не устраняя ее коренную причину.

В заключение, подобные неочевидные ошибки требуют системного подхода к диагностике. Мы должны учитывать все особенности нашего окружения: текущую конфигурацию, версию платформы, наличие и состояние расширений, а также историю обновлений. Сосредоточив усилия на адаптации расширения и проверке целостности метаданных, мы сможем добиться стабильной работы запросов и всей системы в целом.

← На главную