IE2017

Исправление ошибки арифметического переполнения при преобразовании numeric к типу данных numeric при расчете себестоимости

Программирование - Практика программирования

В данной статье описывается один из способов исправления ошибки арифметического переполнения при преобразовании numeric к типу данных numeric, с которой не раз сталкивались многие люди, занимающиеся расчетом себестоимости в базах с большим объёмом данных.

Многие люди, занимающиеся расчетом себестоимости в базах с большим объёмом данных, не раз сталкивались со следующей ошибкой:

Microsoft SQL Server Native Client 11.0:Ошибка арифметического переполнения при преобразовании numeric к типу данных numeric.

HRESULT=80040E57, SQLSrvr: SQLSTATE=22003, state=8, Severity=10, native=8115, line=1

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

  1. Запускаем проведение проблемного документа расчета с/с в режиме отладки и дожидаемся ошибки.
  2. Смотрим, на какой строке кода происходит ошибка, и идём в конфигуратор. В моём случае это была строка 2519: Запрос.ВыполнитьПакет()[1].Выбрать() модуля объекта документа "Расчет себестоимости"
  3. В тексте запроса ищем функцию ВЫРАЗИТЬ
  4. Если есть строчки ВЫРАЗИТЬ(<ВыбранноеПоле> КАК ЧИСЛО (23,10))  изменяем их на ВЫРАЗИТЬ(<ВыбранноеПоле> КАК ЧИСЛО (25,10)) и радуемся результату

В моём случае текст запроса был изменен следующим образом:

        "ВЫБРАТЬ
		|	УзлыКорректировки.НомерУзла КАК НомерУзла,
		|	ВЫРАЗИТЬ(МАКСИМУМ(УзлыКорректировки.Стоимость) КАК ЧИСЛО(25, 10)) КАК СвободныйКоэффициент,
		|	ВЫРАЗИТЬ(МАКСИМУМ(УзлыКорректировки.СтоимостьБезНДС) КАК ЧИСЛО(25, 10)) КАК СвободныйКоэффициентБезНДС,
		|	ВЫРАЗИТЬ(МАКСИМУМ(УзлыКорректировки.ПостояннаяРазница) КАК ЧИСЛО(25, 10)) КАК СвободныйКоэффициентПостояннаяРазница,
		|	ВЫРАЗИТЬ(МАКСИМУМ(УзлыКорректировки.ВременнаяРазница) КАК ЧИСЛО(25, 10)) КАК СвободныйКоэффициентВременнаяРазница,
		|	ВЫРАЗИТЬ(МАКСИМУМ(УзлыКорректировки.СтоимостьДопРасходы) КАК ЧИСЛО(25, 10)) КАК СвободныйКоэффициентДопрасходы,
		|	ВЫРАЗИТЬ(МАКСИМУМ(УзлыКорректировки.СтоимостьДопРасходыБезНДС) КАК ЧИСЛО(25, 10)) КАК СвободныйКоэффициентДопрасходыБезНДС,
		|	МИНИМУМ(УзлыКорректировки.ВременнаяРазницаЗнак * ЕСТЬNULL(ВтТаблицаРешений.ВременнаяРазницаЗнак, 1)) КАК ВременнаяРазницаЗнак,
		|	МИНИМУМ(УзлыКорректировки.ПостояннаяРазницаЗнак * ЕСТЬNULL(ВтТаблицаРешений.ПостояннаяРазницаЗнак, 1)) КАК ПостояннаяРазницаЗнак,
		|	(ВЫРАЗИТЬ(СУММА(ЕСТЬNULL(ВтТаблицаРешений.Стоимость, 0) * ЕСТЬNULL(ПеремещенияСписания.Количество, 0)) КАК ЧИСЛО(25, 10))) / УзлыКорректировки.Количество КАК Стоимость,
		|	(ВЫРАЗИТЬ(СУММА(ЕСТЬNULL(ВтТаблицаРешений.СтоимостьБезНДС, 0) * ЕСТЬNULL(ПеремещенияСписания.Количество, 0)) КАК ЧИСЛО(25, 10))) / УзлыКорректировки.Количество КАК СтоимостьБезНДС,
		|	(ВЫРАЗИТЬ(СУММА(ЕСТЬNULL(ВтТаблицаРешений.ПостояннаяРазница, 0) * ЕСТЬNULL(ПеремещенияСписания.Количество, 0)) КАК ЧИСЛО(25, 10))) / УзлыКорректировки.Количество КАК ПостояннаяРазница,
		|	(ВЫРАЗИТЬ(СУММА((ЕСТЬNULL(ВтТаблицаРешений.ВременнаяРазница, 0) + ВЫБОР
		|				КОГДА ПеремещенияСписания.КосвенныеЗатратыНУ
		|					ТОГДА ЕСТЬNULL(ВтТаблицаРешений.Стоимость, 0)
		|				ИНАЧЕ 0
		|			КОНЕЦ + ВЫБОР
		|				КОГДА ПеремещенияСписания.КосвенныеЗатратыНУ
		|					ТОГДА ЕСТЬNULL(ВтТаблицаРешений.СтоимостьДопРасходы, 0)
		|				ИНАЧЕ 0
		|			КОНЕЦ) * ЕСТЬNULL(ПеремещенияСписания.Количество, 0)) КАК ЧИСЛО(25, 10))) / УзлыКорректировки.Количество КАК ВременнаяРазница,
		|	(ВЫРАЗИТЬ(СУММА(ЕСТЬNULL(ВтТаблицаРешений.СтоимостьДопРасходы, 0) * ЕСТЬNULL(ПеремещенияСписания.Количество, 0)) КАК ЧИСЛО(25, 10))) / УзлыКорректировки.Количество КАК СтоимостьДопРасходы,
		|	(ВЫРАЗИТЬ(СУММА(ЕСТЬNULL(ВтТаблицаРешений.СтоимостьДопРасходыБезНДС, 0) * ЕСТЬNULL(ПеремещенияСписания.Количество, 0)) КАК ЧИСЛО(25, 10))) / УзлыКорректировки.Количество КАК СтоимостьДопРасходыБезНДС
		|ПОМЕСТИТЬ ВременнаяТаблицаРешений
		|ИЗ
		|	ВтУзлыКорректировки КАК УзлыКорректировки
		|		ЛЕВОЕ СОЕДИНЕНИЕ ВтПеремещенияСписания КАК ПеремещенияСписания
		|		ПО УзлыКорректировки.НомерУзла = ПеремещенияСписания.НомерУзлаПриемник
		|		ЛЕВОЕ СОЕДИНЕНИЕ ВтТаблицаРешений КАК ВтТаблицаРешений
		|		ПО (ПеремещенияСписания.НомерУзлаИсточник = ВтТаблицаРешений.НомерУзла)
		|ГДЕ
		|	УзлыКорректировки.Количество <> 0
		|	И ЕСТЬNULL(ВтТаблицаРешений.Стоимость, 0) * ЕСТЬNULL(ПеремещенияСписания.Количество, 0) > -999999999.999999999
		|	И ЕСТЬNULL(ВтТаблицаРешений.Стоимость, 0) * ЕСТЬNULL(ПеремещенияСписания.Количество, 0) < 999999999.999999999
		|
		|СГРУППИРОВАТЬ ПО
		|	УзлыКорректировки.НомерУзла,
		|	УзлыКорректировки.Количество
		|
		|ИНДЕКСИРОВАТЬ ПО
		|	НомерУзла
		|;
		|

См. также

Лучшие комментарии
1. rjhev korum (корум) 310 13.12.16 11:05 Сейчас в теме
Чудны творения твои, 1с...
АндрейКр; +1 Ответить
Остальные комментарии
1. rjhev korum (корум) 310 13.12.16 11:05 Сейчас в теме
Чудны творения твои, 1с...
АндрейКр; +1 Ответить
2. Роберт В е р т и н с к и й (v3rter) 13.12.16 15:33 Сейчас в теме
Плюсану, поскольку сталкивался и лечил такие проблемы в самопальных складских программах.
3. Allexey (alex_4x) 72 13.03.17 13:15 Сейчас в теме
В данном случае помогло, но это не факт, что всегда поможет.
Проблема может быть не только с длиной целой части, но и длиной дробной части.

Суть ошибки в том, что во время вычисления - SQL не может преобразовать тип внутри вычисления как правило умножения или деления. Решается не обязательно увеличением разрядности, достаточно ВЫРАЗИТЬ( Значение , ХХ,ХХ) использовать для всех вычисляемых аргументов в том числе внутри скобок. Тогда SQL не занимается самодеятельностью по выбору типа внутри самого вычисления и ошибка не происходит.

Ну примерно так:
Было:
 ВЫРАЗИТЬ(СУММА(ЕСТЬNULL(ВтТаблицаРешений.ПостояннаяРазница, 0) * ЕСТЬNULL(ПеремещенияСписания.Количество, 0)) КАК ЧИСЛО(23, 10)))

Будет
ВЫРАЗИТЬ 
СУММА(ВЫРАЗИТЬ ЕСТЬNULL(ПеремещенияСписания.Количество, 0) КАК ЧИСЛО(23, 10) *
 ВЫРАЗИТЬ ЕСТЬNULL(ПеремещенияСписания.Количество, 0) КАК ЧИСЛО(23, 10) )
КАК ЧИСЛО(23, 10)
АндрейКр; +1 Ответить
4. Роберт В е р т и н с к и й (v3rter) 13.03.17 14:23 Сейчас в теме
При таких расчетах могут накапливаться и ошибки округления дробной части, здесь это нивелируется десятью знаками после запятой ЧИСЛО(..., 10). Попутно может всплыть проблема сравнения итогов с нулём или константой, так как из-за накопления ошибок округления дробной части выглядеть она будет как -0.0001 < x <0,0001
5. user781880 (a.artemov) 29.06.17 16:05 Сейчас в теме
Коллеги прошу помощи.
Увеличение разрядности не помогло.
Ошибка осталась. Кто может помочь?

Ошибка при выполнении обработчика - 'ОбработкаПроведения'
по причине:
{ОбщийМодуль.КорректировкаСтоимостиУчетЗатрат.Модуль(403)}: Ошибка при вызове метода контекста (Выполнить)
Док.Записать(РежимЗаписиДокумента.Проведение);
по причине:
Ошибка выполнения запроса
по причине:
Ошибка при выполнении операции над данными:
Microsoft SQL Server Native Client 11.0: Ошибка арифметического переполнения при преобразовании numeric к типу данных numeric.
HRESULT=80040E57, SQLSrvr: SQLSTATE=22003, state=8, Severity=10, native=8115, line=1


Код такой:
СУММА(ВЫРАЗИТЬ(
| ВЫБОР КОГДА УчетЗатрат.ВидДвижения = ЗНАЧЕНИЕ(ВидДвиженияНакопления.Расход) ТОГДА
| УчетЗатрат.Стоимость
| ИНАЧЕ
| 0
| КОНЕЦ
| КАК ЧИСЛО(38,10))) КАК Стоимость
6. Alex Nikulin (Al-77) 54 29.06.17 22:40 Сейчас в теме
7. Alex Nikulin (Al-77) 54 29.06.17 22:40 Сейчас в теме
8. Андрей Артемов (a.artemov) 30.06.17 08:08 Сейчас в теме
Управление производственным предприятием, редакция 1.3 (1.3.89.2)

Если есть возможность помочь для более оперативного общения контакты на почту прислать? У меня каждый день на счету.
9. Ренат (rintik) 6 30.06.17 10:03 Сейчас в теме
А если попробовать поменять
| КАК ЧИСЛО(38,10))) КАК Стоимость

на
| КАК ЧИСЛО(32,10))) КАК Стоимость
10. rjhev korum (корум) 310 30.06.17 12:14 Сейчас в теме
(9) читаем статью, "не хватает знаков ДО запятой", метод решения:
Если есть строчки ВЫРАЗИТЬ(<ВыбранноеПоле> КАК ЧИСЛО (23,10)) изменяем их на ВЫРАЗИТЬ(<ВыбранноеПоле> КАК ЧИСЛО (25,10)) и радуемся результату.

Читаем (9) и понимаем, что уменьшение знаков до запятой не поможет...
11. Alex Nikulin (Al-77) 54 30.06.17 13:28 Сейчас в теме
У меня такая же ситуация, только последняя УТ 11.3.3.231 я уже 2 месяца пытаюсь найти в данных проблему. пробовал увеличить разрядность, помогло на два месяца потом опять стала ошибка.
12. Андрей Артемов (a.artemov) 30.06.17 15:01 Сейчас в теме
(9) Начинали с 25,10 дошли до 38,10 не помогает. ТЬочнее попробовал 40,10 ругнулась что перебор...
13. Андрей Артемов (a.artemov) 01.07.17 07:54 Сейчас в теме
Проблема не решена. Помогите кто может.
14. Андрей Шарапов (Napalmmm) 12.07.17 18:43 Сейчас в теме
Вот и я попал. (37,10) стояло больше двух лет, сейчас не спасло. Решения нет?
15. oleg bu (see888) 12.07.17 19:57 Сейчас в теме
Теперь и я) как перевел базу на с 11.1 на 11.3.4... даже не пойму что он там по кругу выполняет,с каждым выполнением отклонение растет. Что это такое вообще? Кто сможет объяснить:
Дополнительная информация об этапе:
- Отклонение на текущей итерации: 42 631,8
- Отклонение на текущей итерации: 24 780
- Отклонение на текущей итерации: 21 311,8
- Отклонение на текущей итерации: 17 797,43
- Отклонение на текущей итерации: 7 800
- Отклонение на текущей итерации: 20 588,5568513129
- Отклонение на текущей итерации: 20 588,556851313
- Отклонение на текущей итерации: 73 530,5601832607
- Отклонение на текущей итерации: 73 530,5601832608
- Отклонение на текущей итерации: 262 609,1435116457
- Отклонение на текущей итерации: 262 609,1435116456
- Отклонение на текущей итерации: 937 889,7982558771
- Отклонение на текущей итерации: 937 889,798255877
- Отклонение на текущей итерации: 3 349 606,4223424179
- Отклонение на текущей итерации: 3 349 606,422342418
- Отклонение на текущей итерации: 11 962 880,07979435
- Отклонение на текущей итерации: 11 962 880,07979435
- Отклонение на текущей итерации: 42 724 571,71355125
- Отклонение на текущей итерации: 42 724 571,71355125
- Отклонение на текущей итерации: 152 587 756,1198258929
- Отклонение на текущей итерации: 152 587 756,119825893
- Отклонение на текущей итерации: 544 956 271,8565210464
- Отклонение на текущей итерации: 544 956 271,8565210464
- Отклонение на текущей итерации: 1 946 272 399,4875751657
- Отклонение на текущей итерации: 1 946 272 399,4875751656
- Отклонение на текущей итерации: 6 950 972 855,3127684486
- Отклонение на текущей итерации: 6 950 972 855,3127684486
- Отклонение на текущей итерации: 24 824 903 054,688458745
- Отклонение на текущей итерации: 24 824 903 054,688458745
- Отклонение на текущей итерации: 88 660 368 052,4587812321
- Отклонение на текущей итерации: 88 660 368 052,458781232
- Отклонение на текущей итерации: 316 644 171 615,9242186857
Это то что под приложением выдал из состоянии расчета.

А в отладчике последнее значение было таково :
267 488 214 754 648 642 684 559 809,9800832
и это на 85 Итерации из 200 как он показывает.

Что тут вообще происходит?)
Оставьте свое сообщение