Почему конструктор запросов 1С ругается на умножение полей и выдает ошибку «Не верные параметры "*"»?

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

Каждый разработчик 1С рано или поздно сталкивается с удивительным и на первый взгляд необъяснимым поведением платформы. Представьте ситуацию: вы пишете простой и интуитивно понятный запрос, в котором перемножаете два числовых поля — например, цену и количество товара. С точки зрения логики и типов данных в метаданных всё настроено абсолютно верно. Более того, этот запрос прекрасно выполняется в режиме «1С:Предприятие», в коде обработок или в Консоли запросов. Но стоит вам попытаться открыть этот запрос в Конструкторе запросов в Конфигураторе, как система тут же выдает ошибку: «Не верные параметры "*"».

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

Проанализируем ситуацию: в чем суть проблемы?

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


ВЫБРАТЬ
    ПриобретениеТоваровУслугТовары.Количество КАК Количество,
    ПриобретениеТоваровУслугТовары.Цена КАК ТАБ_Цена,
    ПриобретениеТоваровУслугТовары.Количество * ПриобретениеТоваровУслугТовары.Цена КАК СуммаРегл
ИЗ
    Документ.ПриобретениеТоваровУслуг.Товары КАК ПриобретениеТоваровУслугТовары

Оба поля — и Количество, и Цена — имеют строго числовой тип в метаданных конфигурации. Однако Конструктор запросов наотрез отказывается сохранять или редактировать это выражение, ссылаясь на некорректность оператора умножения. При этом попытки обернуть поля в функции ЕСТЬNULL или явно привести их к типу через ВЫРАЗИТЬ не приносят желаемого результата.

Такое поведение объясняется фундаментальным различием между тем, как текст запроса анализируется визуальным Конструктором запросов в Конфигураторе, и тем, как он исполняется непосредственно СУБД на сервере. Выделим несколько ключевых причин этой проблемы и разберем методы их устранения.

Причина 1: Невидимый враг — неразрывные пробелы (символ с кодом 160 / NBSP)

Самая частая и неочевидная причина, из-за которой «спотыкается» парсер Конструктора запросов — это наличие в тексте так называемых неразрывных пробелов (символ с ASCII-кодом 160 или NBSP).

Как они попадают в код? Чаще всего это происходит при копировании фрагментов запросов из мессенджеров, писем, веб-страниц форумов или Skype. Внешне такой пробел ничем не отличается от обычного пробела (символ с кодом 32), но для синтаксического анализатора Конструктора запросов они принципиально различны:

  1. Обычный пробел (код 32) распознается парсером как стандартный разделитель инструкций, операторов и имен полей.
  2. Неразрывный пробел (код 160) парсером Конструктора запросов как разделитель не воспринимается. Платформа пытается интерпретировать его как часть имени поля или оператора. В результате конструкция вида Цена [NBSP]*[NBSP] Количество превращается в глазах парсера в единый нечитаемый идентификатор, что и приводит к ошибке «Не верные параметры "*"».

Почему же тогда этот запрос без проблем работает в режиме «1С:Предприятие» и Консоли запросов? Дело в том, что перед отправкой запроса на СУБД механизм трансляции SDBL (внутренний язык запросов 1С) производит предварительную санитизацию текста запроса, автоматически заменяя все неразрывные пробелы на стандартные. Конструктор же запросов в Конфигураторе производит жесткий локальный статический анализ «как есть», без предварительной очистки текста.

Как решить проблему с неразрывными пробелами:

  1. Ручной ввод выражения. Полностью удалите проблемную строку с операцией умножения в Конструкторе или текстовом редакторе и напишите её заново вручную с клавиатуры. Используйте только стандартную клавишу «Пробел».
  2. Написание без пробелов. В языке запросов 1С необязательно разделять пробелами математические операторы. Напишите выражение слитно: ПриобретениеТоваровУслугТовары.Количество*ПриобретениеТоваровУслугТовары.Цена. В таком случае скрытым символам просто негде будет появиться.
  3. Автоматическая замена в Конфигураторе. Выделите фрагмент текста запроса, нажмите комбинацию клавиш Ctrl + H (Замена). В поле «Найти» скопируйте подозрительный пробел из текста запроса (или введите его, зажав клавишу Alt и набрав на цифровой клавиатуре 0160). В поле «Заменить на» введите обычный пробел с клавиатуры. Нажмите «Заменить все».

Причина 2: Жесткий статический анализ типов и составные типы данных

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

Если хотя бы одно из полей (например, в измененной или нетиповой конфигурации) имеет составной тип данных, включающий помимо числа ссылку, строку или булево значение, Конструктор превентивно блокирует операцию умножения. Он логично предполагает, что при наличии в базе данных нечислового значения СУБД выдаст критическую ошибку выполнения.

Как решить проблему типизации:

Для обхода этой проблемы необходимо жестко указать Конструктору, что мы гарантированно работаем с числовым типом данных. Обычная функция ЕСТЬNULL(Поле, 0) не всегда решает проблему, так как она лишь заменяет значение NULL на дефолтное, но не меняет исходное описание доступных типов поля. В схожих ситуациях, когда требуется сопоставить разнородные типы, можно использовать методику сравнения строк с представлениями ссылок в запросах.

Мы должны применить оператор ВЫРАЗИТЬ. Рассмотрим правильный пример приведения типов:


ВЫБРАТЬ
    ВЫРАЗИТЬ(ПриобретениеТоваровУслугТовары.Количество КАК ЧИСЛО(15, 3)) 
    * 
    ВЫРАЗИТЬ(ПриобретениеТоваровУслугТовары.Цена КАК ЧИСЛО(15, 2)) КАК СуммаРегл
ИЗ
    Документ.ПриобретениеТоваровУслуг.Товары КАК ПриобретениеТоваровУслугТовары

Использование оператора ВЫРАЗИТЬ сообщает Конструктору запросов, что данные поля на этапе выполнения будут приведены к конкретному числовому типу заданной разрядности. После этого синтаксический анализатор Конфигуратора без лишних вопросов пропустит операцию умножения.

Причина 3: Неопределенные типы колонок во временных таблицах

Еще один сценарий, при котором возникает подобное поведение — работа с временными таблицами, которые формируются динамически или передаются в запрос в качестве параметров (например, при передаче Таблицы Значений в запрос).

Если вы помещаете данные во временную таблицу и при этом предварительно не типизируете колонки, Конструктор запросов может присвоить им тип ЛюбаяСсылка или оставить тип неопределенным. Попытка перемножить такие колонки в последующих пакетах запроса гарантированно вызовет ошибку «Не верные параметры "*"». Для быстрого обнаружения подобных проблем во временных таблицах и запросах можно использовать инструмент для проверки запросов на нетипизированные поля и составные типы.

Решение для временных таблиц:

Всегда явно типизируйте поля при их помещении во временные таблицы. Разберем пример правильного создания временной таблицы с явным указанием типов:


ВЫБРАТЬ
    ВЫРАЗИТЬ(ИсходныеДанные.Цена КАК ЧИСЛО(15, 2)) КАК Цена,
    ВЫРАЗИТЬ(ИсходныеДанные.Количество КАК ЧИСЛО(15, 3)) КАК Количество
ПОМЕСТИТЬ ВТ_ОчищенныеДанные
ИЗ
    &ТаблицаИсточника КАК ИсходныеДанные
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    ВТ_ОчищенныеДанные.Цена * ВТ_ОчищенныеДанные.Количество КАК Сумма
ИЗ
    ВТ_ОчищенныеДанные КАК ВТ_ОчищенныеДанные

Благодаря явному приведению типов при создании временной таблицы ВТ_ОчищенныеДанные, во втором запросе пакета Конструктор без проблем позволит нам совершать любые арифметические операции над этими полями.

Причина 4: Особенности и баги конкретных релизов платформы 1С

Иногда странное поведение Конструктора запросов связано с внутренними ошибками (багами) конкретных релизов технологической платформы «1С:Предприятие 8». Например, в некоторых версиях линеек 8.3.16 и 8.3.17 наблюдались локальные сбои в работе парсера метаданных Конфигуратора при анализе вложенных запросов и левых соединений, из-за чего валидация простых арифметических выражений завершалась ошибкой.

Если вы исключили проблемы с неразрывными пробелами и проверили типы данных, выполните следующие действия:

  1. Попробуйте открыть и сохранить этот же запрос на другом релизе платформы (более новом или, наоборот, стабильном старом).
  2. Очистите кэш Конфигуратора. Локальный кэш метаданных может содержать устаревшие или поврежденные схемы таблиц, из-за чего Конструктор запросов некорректно определяет типы полей документов.

Подведем итоги

Столкнувшись с непонятным поведением Конструктора запросов при умножении полей, не спешите переписывать архитектуру запроса или отказываться от использования Конструктора. В 95% случаев проблема решается выполнением трех простых шагов:

  1. Удалите пробелы вокруг знака умножения * и напишите их заново вручную, чтобы избавиться от скрытых символов с кодом 160.
  2. Примените явное приведение типов с помощью конструкции ВЫРАЗИТЬ(... КАК ЧИСЛО) для полей, участвующих в операции.
  3. Убедитесь, что исходные поля в метаданных конфигурации не имеют составного типа данных, содержащего нечисловые значения.

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

← На главную