2013-08-21 502 views
0

我的問題:我有一個表格(從Excel導入到SQL Server 2008),它以NVARCHAR(255)格式存儲數字。將NVARCHAR轉換爲MONEY或FLOAT格式

試圖將這些列轉換爲FLOATMONEYNUMERIC失敗CONVERTCAST功能:

ORIGBAL = CAST(ORIGBAL AS FLOAT) 
ORIGBAL = CAST(ORIGBAL AS MONEY) 
ORIGBAL = CAST(ORIGBAL AS MONEY) 
ORIGBAL = CONVERT(decimal(12,2),ORIGBAL) 

該消息是在所有情況下(或類似的失敗的錯誤消息):

將數據類型nvarchar轉換爲數字時出錯。

+2

你能展示一些數據,你想轉換的例子嗎? –

回答

2

聽起來像,因爲你有數字數據存儲在一個字符串列,你有錯誤的數據。識別它的方法之一是:

SELECT key_column, ORIGBAL 
    FROM dbo.tablename 
    WHERE ORIGBAL LIKE '%[^-.0-9]%'; 

修正數據(可能包含逗號,但可能的傷害比這更糟糕,像一些價值觀具有完全非數字數據 - 否則轉換爲MONEY應該有工作) 。如果您發現很多行包含逗號,則可以簡單地運行更新:

UPDATE dbo.tablename SET ORIGBAL = REPLACE(ORIGBAL, ',', ''); 

然後再次運行上述查詢。如果沒有行被返回,現在你可以轉換爲「普通」數字類型,而不是MONEYFLOAT,這真的應該保留用於特定的場景恕我直言。

沒有固定的數據,你可以讓你的生活更加複雜,在所有的查詢使用CASE表達:

SELECT key_column, CONVERT(DECIMAL(12,2), CASE 
    WHEN ORIGBAL LIKE '%[^-.0-9]%' THEN ORIGBAL END 
FROM dbo.tablename 
... 

這將產生NULL值,而不是壞的,非數值。然而,它仍然可能失敗,例如該表達式將通過0.0.0.44.02,這顯然不能轉換爲小數。舉個例子:

DECLARE @x TABLE(ORIGBAL NVARCHAR(255)); 

INSERT @x VALUES('bob'),('0.0.0.44.02'),('32500.40'); 

SELECT ORIGBAL, [status] = CASE WHEN ORIGBAL LIKE '%[^.0-9]%' 
    THEN 'needs correcting' ELSE 'all good' END 
FROM @x; 

結果:

bob   needs correcting 
0.0.0.44.02 all good 
32500.40  all good 

爲了識別與多個小數點的情況下,你可以這樣做:

SELECT ORIGBAL, [status] = CASE WHEN ORIGBAL LIKE '%[^.0-9]%' 
    OR LEN(ORIGBAL)-LEN(REPLACE(ORIGBAL,'.','')) > 1 
    THEN 'needs correcting' ELSE 'all good' END 
FROM @x; 

結果:

bob   needs correcting 
0.0.0.44.02 needs correcting 
32500.40  all good 

你還是可能具有超過最終值的值轉換,例如'123456789.56'對於DECIMAL(12,2)太大。

在SQL Server 2012中,你將有速記上述表達式:

SELECT key_column, TRY_CONVERT(DECIMAL(12,2), ORIGBAL) 
FROM dbo.tablename 
... 

...這產量甚至像0.0.0.44.02更復雜的值NULL值。

+0

謝謝。任何想法如何我可以修復這些數據?我能看到的是例如存儲了32500.40,格式又是NVARCHAR(255)。我無法導出這些數據,因此需要在SQL中進行轉換。 –

+0

你能演示'32500.40'不能轉換爲'DECIMAL'或'NUMERIC'嗎?我非常懷疑價值具體是問題(除非列中包含我們看不到的其他非打印字符)。 –

+0

ORIGBAL NOT LIKE'%[^ - 。09]%'條件對於整個數據庫是正確的。上面的CONVERT,REPLACE函數不起作用,我已經將空格替換爲'。'。事先,這是我從32500 40格式到32500.40格式的方式。所以你建議從頭開始?我沒有看到任何隱藏的字符背後... –

0

CAST對逗號和美元符號的反應並不好。 CONVERT可能會帶來更好的運氣......

SELECT CONVERT(money, '$1,123.45') 

如果你必須有它的十進制轉換成錢,然後十進制...

SELECT CAST(CONVERT(money, '$1,123.45') AS decimal(12,2)) 
+0

'SELECT CAST('$ 1,123.45'as money);'工作得很好 - 在這種情況下CAST和CONVERT沒有區別。 –

+0

@Aaron,你說得對。我可以在我的測試中發誓失敗,但我只是重試它。我猜,黃油手指。 – dazedandconfused