При проведении или отражении документов производства и переработки давальческого сырья (например, документов Этап производства или Отчет давальцу) в регламентированном учете системы 1С:ERP пользователи могут столкнуться с аварийным завершением операции: Microsoft OLE DB Driver for SQL Server: Ошибка арифметического переполнения при преобразовании numeric к типу данных numeric. HRESULT=80040E57, SQLSrvr: SQLSTATE=22003, native=8115. Разберем детально, почему возникает эта ошибка, как работает механизм вычислений в СУБД MS SQL Server и какими способами можно восстановить работоспособность закрытия месяца и отражения документов.
Выясним причину аварии на уровне базы данных. В конфигурации 1С:ERP при детализированном учете себестоимости формируются сложные пакетные запросы, которые обращаются к регистрам СебестоимостьТоваров, ДетализацияСебестоимостиПартийПродукции и сопутствующим таблицам затрат.
Рассмотрим выражение, на котором происходит сбой:
ВЫРАЗИТЬ((Т.Количество / Детализация.Количество) * Детализация.СтоимостьРегл КАК ЧИСЛО(31,2)) КАК СтоимостьРегл
Проанализируем, как MS SQL Server вычисляет такое выражение. При операциях с типом данных numeric СУБД динамически рассчитывает точность (precision) и масштаб (scale) для каждого промежуточного подвыражения:
(Т.Количество / Детализация.Количество) порождает результат с максимальным увеличением разрядности дробной части. Для сохранения точности СУБД отводит под масштаб значительную часть доступной разрядности.Детализация.СтоимостьРегл суммарная необходимая разрядность превышает лимит MS SQL Server в 38 десятичных знаков. В этой ситуации СУБД принудительно обрезает масштаб, высвобождая место под целую часть.ВЫРАЗИТЬ(... КАК ЧИСЛО(31,2)) (транслируемая в CAST).Вторая составляющая проблемы — накопление аномально больших чисел (триллионов и квадриллионов) в регистрах учета. Это происходит в результате сбоя численных методов при решении СЛАУ или циклического списания затрат, когда система пытается распределить ненулевую стоимость на стремящуюся к нулю или микроскопическую количественную базу (например, при наличии остатков порядка 0.00001 в цеховых кладовых).
Посмотрим на практическое решение в коде конфигуратора или расширения. Если нам необходимо срочно провести документы и отразить их в учете, изменим порядок действий в проблемном запросе общего модуля формирования проводок.
Вместо предварительного деления выполним сначала умножение стоимостного показателя на количество, а затем деление на базу:
// Исходный вариант, приводящий к переполнению промежуточного типа:
// ВЫРАЗИТЬ((Т.Количество / Детализация.Количество) * Детализация.СтоимостьРегл КАК ЧИСЛО(31,2)) КАК СтоимостьРегл
// Скорректированный вариант:
ВЫРАЗИТЬ(Детализация.СтоимостьРегл / Детализация.Количество * Т.Количество КАК ЧИСЛО(31,2)) КАК СтоимостьРегл,
ВЫРАЗИТЬ(Детализация.НДСРегл / Детализация.Количество * Т.Количество КАК ЧИСЛО(31,2)) КАК НДСРегл,
ВЫРАЗИТЬ(Детализация.СтоимостьУпр / Детализация.Количество * Т.Количество КАК ЧИСЛО(31,2)) КАК СтоимостьУпр,
ВЫРАЗИТЬ(Детализация.НДСУпр / Детализация.Количество * Т.Количество КАК ЧИСЛО(31,2)) КАК НДСУпр,
ВЫРАЗИТЬ(Детализация.ПостояннаяРазница / Детализация.Количество * Т.Количество КАК ЧИСЛО(31,2)) КАК ПостояннаяРазница,
ВЫРАЗИТЬ(Детализация.ВременнаяРазница / Детализация.Количество * Т.Количество КАК ЧИСЛО(31,2)) КАК ВременнаяРазница
Также можно воспользоваться принудительным ограничением разрядности промежуточного коэффициента через функцию ВЫРАЗИТЬ непосредственно внутри скобок, чтобы частное не расширялось до 38 знаков:
ВЫРАЗИТЬ(ВЫРАЗИТЬ(Т.Количество / Детализация.Количество КАК ЧИСЛО(15, 6)) * Детализация.СтоимостьРегл КАК ЧИСЛО(31,2)) КАК СтоимостьРегл
Такой подход явно задает для СУБД тип данных промежуточного коэффициента распределения и устраняет переполнение при умножении.
Разберем по шагам, как локализовать некорректные записи в базе данных, провоцирующие гигантские суммы:
ДетализацияСебестоимостиПартийПродукции: напишем проверочный запрос в консоли запросов с отбором по модулю сумм, выходящих за рамки здравого смысла:
ВЫБРАТЬ
Т.ПериодРегистрации,
Т.Регистратор,
Т.Номенклатура,
Т.Количество,
Т.СтоимостьРегл,
Т.СтоимостьУпр
ИЗ
РегистрСведений.ДетализацияСебестоимостиПартийПродукции КАК Т
ГДЕ
Т.Номенклатура В (&СписокПроблемнойНоменклатуры)
И (Т.СтоимостьРегл > 100000000000 ИЛИ Т.СтоимостьРегл < -100000000000)
СебестоимостьТоваров. Если в цепочке документов используется передача в цеховую кладовую, а затем списание на выпуск, проверим наличие микроскопических «хвостов» количества (например, остаток 0.00001 при стоимости в несколько сотен тысяч рублей). Наличие таких делений порождает расчетную цену единицы, стремящуюся к бесконечности.КорректировкаРегистров на конец предшествующего месяца, обнулив аномальные стоимостные или количественные хвосты по соответствующим ключам аналитики.Рассмотрим системное решение. Фирма «1С» зафиксировала ошибку в подсистеме расчета себестоимости и распределения затрат по статьям калькуляции при включенном детализированном учете и использовании цеховых кладовых (ошибка зарегистрирована под номером 00-00934588).
Для гарантированного устранения проблемы выполним следующие действия:
ЗакрытиеМесяца.ОтражениеДокументовВРеглУчете. Аномальные суммы будут списаны корректно, и документы отразятся в учете без системных сбоев.