2015-08-27 55 views
2

我使用BCP將大量數據導入包含所有字符串的SQL Server。爲了保持數據庫的完整性,我正在修改所有的列,以查找正確的元數據。十進制高精度和規模創建'算術溢出錯誤'

我有一個當前的字符串列,它實際上是十進制值,並且需要修改列以使其成爲十進制(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)其中p =精度和s =比例;我的印象是,我的最大精度(p)爲38,爲什麼會出現這個錯誤?有什麼建議麼?我必須不失去任何精度。

+1

您確定在該列中沒有任何非數字值嗎? – APH

+0

@APH –

回答

3

你可以嘗試尋找故障行(S)與此:

select Measure from Result 
where TRY_CONVERT(DECIMAL(24,19),Measure) 
is Null And Measure is Not Null; 
+0

列中沒有非數字值這會導致誤報,因爲精度不正確。 –

+2

我已經使用@Jeff Orris查詢來運行一些測試以找到所需的精度,並且他們轉向正確。我相信有一些非數字值。 –

+0

@JonC我跑了建議的查詢,並得到以下2個結果:'132000' '116000' ....爲什麼這些不會轉換爲小數? –

1

從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 

在此示例中,轉換不應該由字符串或空字符串中的整數失敗。

+1

如果您使用示例(123.00)嘗試@Jeff Orris查詢,則會得到(5,2)作爲所需的精確度,但他的查詢實際上是按照您正確說明的方式計算存儲在小數點左側和右側的數字。 –

+0

建議的查詢將計算小數點,所以p將比需要的數量多1 –

+0

你是對的@JonC。 –