В практике работы с конфигурацией «1С:Розница 2.2» системные администраторы и программисты часто сталкиваются со специфической ошибкой при попытке открыть документ Установка цен номенклатуры. Проблема особенно актуальна после переноса данных из предыдущих версий (например, 1С 7.7) или при использовании механизмов автоматической загрузки через Универсальный обмен данными XML. Ошибка проявляется в виде системного сообщения: «Ошибка SQL: Деление на 0. Деление на 0 значения типа Numeric». При этом документ может быть визуально заполнен верно, а его копия открываться без проблем.
В данной статье мы разберем причины возникновения этой ситуации, проанализируем запрос, на котором происходит сбой, и предложим пошаговый алгоритм исправления данных.
Рассмотрим ситуацию глубже. Ошибка возникает не в момент записи данных, а в момент формирования динамического запроса при открытии формы документа. Конфигурация «Розница 2.2» при открытии формы УстановкаЦенНоменклатуры выполняет запрос для расчета текущих действующих цен и процента отклонения новой цены от старой. Проанализируем фрагмент запроса, который вызывает исключение:
| ВЫРАЗИТЬ(ВЫБОР
| КОГДА ЦеныНоменклатуры.Цена <> 0
| ТОГДА 100 * (Товары.Цена - ВЫБОР
| КОГДА ЕСТЬNULL(ЦеныНоменклатуры.Упаковка, &ПустаяУпаковка) = Товары.Упаковка
| ТОГДА ЕСТЬNULL(ЦеныНоменклатуры.Цена, 0)
| ИНАЧЕ ЕСТЬNULL(ЦеныНоменклатуры.Цена, 0) / ЕСТЬNULL(ЦеныНоменклатуры.Упаковка.Коэффициент, 1) * ЕСТЬNULL(Товары.Упаковка.Коэффициент, 1)
| КОНЕЦ) / ВЫБОР
| КОГДА ЕСТЬNULL(ЦеныНоменклатуры.Упаковка, &ПустаяУпаковка) = Товары.Упаковка
| ТОГДА ЕСТЬNULL(ЦеныНоменклатуры.Цена, 0)
| ИНАЧЕ ЕСТЬNULL(ЦеныНоменклатуры.Цена, 0) / ЕСТЬNULL(ЦеныНоменклатуры.Упаковка.Коэффициент, 1) * ЕСТЬNULL(Товары.Упаковка.Коэффициент, 1)
| КОНЕЦ
| ИНАЧЕ 0
| КОНЕЦ КАК ЧИСЛО(19, 2)) КАК Процент
Проанализируем ситуацию: в запросе используется функция ЕСТЬNULL(ЦеныНоменклатуры.Упаковка.Коэффициент, 1). На первый взгляд кажется, что система защищена от деления на ноль. Однако здесь кроется главная техническая ловушка: если ссылка на Упаковку существует (она не NULL), но в самой карточке упаковки в поле Коэффициент записано значение 0, функция ЕСТЬNULL вернет этот самый ноль. SQL-сервер, выполняя операцию деления, мгновенно прерывает выполнение запроса с ошибкой.
Выясним причину, почему в базе появляются нулевые коэффициенты:
Упаковка, но не заполнить обязательный реквизит Коэффициент, который по умолчанию в базе данных инициализируется нулем.ЦеныНоменклатуры или в табличной части документа указана ссылка на несуществующую упаковку («Объект не найден»), обращение через точку к реквизиту Коэффициент также может вернуть 0 в контексте выполнения SQL-запроса.Прежде чем что-то исправлять, нам необходимо найти «виновника». Проанализируем справочник упаковок и единиц измерения. Для этого воспользуемся внешней обработкой «Консоль запросов» и выполним следующий код:
ВЫБРАТЬ
Упаковки.Ссылка КАК Ссылка,
Упаковки.Владелец КАК Владелец,
Упаковки.Наименование КАК Наименование,
Упаковки.Коэффициент КАК Коэффициент
ИЗ
Справочник.УпаковкиНоменклатуры КАК Упаковки
ГДЕ
Упаковки.Коэффициент <= 0
Если запрос вернул результат, значит, мы нашли корень проблемы. Каждая такая запись в справочнике будет приводить к ошибке деления на ноль при попытке рассчитать цену в разрезе этой упаковки.
Разберем, как исправить найденные ошибки. Если записей много, воспользуемся стандартной обработкой «Групповое изменение реквизитов» (встроена во все современные конфигурации на базе БСП):
Упаковки номенклатуры.Коэффициент Меньше или равно 0.Коэффициент и установим новое значение 1.Важно: Убедитесь, что для базовых единиц измерения (которые в Рознице 2.2 выступают в роли упаковок) коэффициент действительно должен быть равен 1. В 99% случаев это именно так.
Иногда проблема кроется не только в справочнике, но и в уже записанных движениях регистра сведений. Если в регистре ЦеныНоменклатуры зафиксирована запись, где поле Упаковка пустое, а система ожидает коэффициент, может возникнуть сбой. Рассмотрим запрос для проверки регистра:
ВЫБРАТЬ
Цены.Номенклатура,
Цены.ВидЦены,
Цены.Период,
Цены.Упаковка
ИЗ
РегистрСведений.ЦеныНоменклатуры КАК Цены
ГДЕ
Цены.Упаковка = ЗНАЧЕНИЕ(Справочник.УпаковкиНоменклатуры.ПустаяСсылка)
И Цены.Цена <> 0
Если вы обнаружили такие записи, проанализируйте, какая единица измерения должна быть там указана. Часто помогает простое перепроведение документов установки цен после того, как были исправлены ошибки в справочнике упаковок.
Посмотрим на ситуацию, описанную пользователем на форуме: «Если этот же документ скопировать, то форма открывается». Это происходит потому, что при копировании в 1С вызывается процедура ПриКопировании, и форма открывается как для нового (еще не записанного в базу) объекта. В этот момент алгоритмы расчета цен в форме могут использовать упрощенные механизмы или не находить соответствий в регистре сведений для «нового» документа, что позволяет избежать выполнения злополучного участка SQL-кода.
Чтобы избежать подобных ошибок в будущем при повторных загрузках данных, рекомендуется внести изменения в правила обмена (КМТ):
ПередЗагрузкой для справочника упаковок добавьте проверку: если значение коэффициента не передано или равно 0, принудительно устанавливайте Значение = 1.Набор упаковок у номенклатуры. Если используется индивидуальный набор, убедитесь, что структура подчиненного справочника создана корректно.Подведем итог: ошибка деления на ноль в Установке цен номенклатуры — это практически всегда следствие некорректных данных в справочнике упаковок (коэффициент = 0). Исправление коэффициентов на единицу в справочнике и регистре цен полностью устраняет проблему и позволяет документу открываться в штатном режиме.