具有高精度和小数位数的小数创建 'Arithmetic Overflow Error'
Decimal with high precision and scale creating 'Arithmetic Overflow Error'
我使用 BCP 将大量数据导入 SQL 服务器,其中包含所有字符串。为了进一步保持数据库的完整性,我正在更改所有列以获得正确的元数据。
我有一个当前字符串列,它实际上充满了十进制值,需要更改该列以使其成为十进制 (p, s)。
由于数据量大,我写了下面的查询来获取小数点前后字符串的最大长度;添加小数点前后的字符串长度以获得精度。以下查询将显示我到达的结果:
SELECT
'('
+
CAST(MAX(LEN(LEFT(Measure, LEN(Measure) - LEN(SUBSTRING(Measure, CHARINDEX('.', Measure) , 255)))))
+
MAX(LEN(SUBSTRING(Measure, CHARINDEX('.', Measure) +1, 255))) AS varchar(5))
+
','
+ CAST(MAX(LEN(SUBSTRING(Measure, CHARINDEX('.', Measure) +1, 255))) AS varchar(5))
+
')' AS 'max[p,s]'
FROM
Result
结果如下:
max[p,s]
--------
(24,19)
当我通过以下说明更改列时:
ALTER TABLE Result
ALTER COLUMN Measure DECIMAL (24,19)
我收到以下错误:
Msg 8115, Level 16, State 8, Line 1 Arithmetic overflow error
converting varchar to data type numeric. The statement has been
terminated.
(p,s) where p = precision and s=scale;我的印象是我的最大精度 (p) 可以达到 38。为什么会出现此错误?有什么建议么?重要的是我不能失去任何精度。
您可以尝试使用以下方法查找坏行:
select Measure from Result
where TRY_CONVERT(DECIMAL(24,19),Measure)
is Null And Measure is Not Null;
来自 MSDN decimal and numeric (Transact-SQL)
p (precision)
The maximum total number of decimal digits that will be stored, both to the left and to the right of the decimal point. The precision must be a value from 1 through the maximum precision of 38. The default precision is 18.
要获得精度,请使用:
SELECT MAX(LEN(Measure)) AS max_precision_needed
FROM Result
上面的查询没有减去小数点,因为字符串可能包含一个根本没有小数点的整数。它为您提供了可能的最大需求。
示例:
数字 123.00 需要具有以下精度的字段;十进制(5,2)
在下面的示例中,计算出所需的精度后,就可以进行转换了。
DECLARE @measures TABLE ( measure VARCHAR(50) );
INSERT INTO @measures( measure ) VALUES ( '123' )
INSERT INTO @measures( measure ) VALUES ( '123.00' )
INSERT INTO @measures( measure ) VALUES ( '123.001' )
INSERT INTO @measures( measure ) VALUES ( '.123' )
INSERT INTO @measures( measure ) VALUES ( '0.123' )
INSERT INTO @measures( measure ) VALUES ( ' ' )
SELECT '(' + CAST(MAX(LEN(measure)) - 1 AS VARCHAR(5)) + '.' + CAST(MAX(LEN(SUBSTRING(measure, CHARINDEX('.', measure) + 1, 255))) AS VARCHAR(5)) + ')'
FROM @measures
SELECT ISNULL(CONVERT(DECIMAL(6, 3), CASE WHEN CHARINDEX('.', measure) = 0 THEN measure + '.0' ELSE measure END), 0.0)
FROM @measures
在此示例中,转换不应因字符串中的整数或空字符串而失败。
我使用 BCP 将大量数据导入 SQL 服务器,其中包含所有字符串。为了进一步保持数据库的完整性,我正在更改所有列以获得正确的元数据。
我有一个当前字符串列,它实际上充满了十进制值,需要更改该列以使其成为十进制 (p, s)。
由于数据量大,我写了下面的查询来获取小数点前后字符串的最大长度;添加小数点前后的字符串长度以获得精度。以下查询将显示我到达的结果:
SELECT
'('
+
CAST(MAX(LEN(LEFT(Measure, LEN(Measure) - LEN(SUBSTRING(Measure, CHARINDEX('.', Measure) , 255)))))
+
MAX(LEN(SUBSTRING(Measure, CHARINDEX('.', Measure) +1, 255))) AS varchar(5))
+
','
+ CAST(MAX(LEN(SUBSTRING(Measure, CHARINDEX('.', Measure) +1, 255))) AS varchar(5))
+
')' AS 'max[p,s]'
FROM
Result
结果如下:
max[p,s]
--------
(24,19)
当我通过以下说明更改列时:
ALTER TABLE Result
ALTER COLUMN Measure DECIMAL (24,19)
我收到以下错误:
Msg 8115, Level 16, State 8, Line 1 Arithmetic overflow error converting varchar to data type numeric. The statement has been terminated.
(p,s) where p = precision and s=scale;我的印象是我的最大精度 (p) 可以达到 38。为什么会出现此错误?有什么建议么?重要的是我不能失去任何精度。
您可以尝试使用以下方法查找坏行:
select Measure from Result
where TRY_CONVERT(DECIMAL(24,19),Measure)
is Null And Measure is Not Null;
来自 MSDN decimal and numeric (Transact-SQL)
p (precision) The maximum total number of decimal digits that will be stored, both to the left and to the right of the decimal point. The precision must be a value from 1 through the maximum precision of 38. The default precision is 18.
要获得精度,请使用:
SELECT MAX(LEN(Measure)) AS max_precision_needed
FROM Result
上面的查询没有减去小数点,因为字符串可能包含一个根本没有小数点的整数。它为您提供了可能的最大需求。
示例: 数字 123.00 需要具有以下精度的字段;十进制(5,2)
在下面的示例中,计算出所需的精度后,就可以进行转换了。
DECLARE @measures TABLE ( measure VARCHAR(50) );
INSERT INTO @measures( measure ) VALUES ( '123' )
INSERT INTO @measures( measure ) VALUES ( '123.00' )
INSERT INTO @measures( measure ) VALUES ( '123.001' )
INSERT INTO @measures( measure ) VALUES ( '.123' )
INSERT INTO @measures( measure ) VALUES ( '0.123' )
INSERT INTO @measures( measure ) VALUES ( ' ' )
SELECT '(' + CAST(MAX(LEN(measure)) - 1 AS VARCHAR(5)) + '.' + CAST(MAX(LEN(SUBSTRING(measure, CHARINDEX('.', measure) + 1, 255))) AS VARCHAR(5)) + ')'
FROM @measures
SELECT ISNULL(CONVERT(DECIMAL(6, 3), CASE WHEN CHARINDEX('.', measure) = 0 THEN measure + '.0' ELSE measure END), 0.0)
FROM @measures
在此示例中,转换不应因字符串中的整数或空字符串而失败。