SQL Server到了目前的2014版本有三個函數是用來轉換數據格式的。雖說之前版本中已經有CAST和CONVERT這兩個函數來干這個事情。問題是,一旦往目標數據類型轉換失敗就會造成報錯。
TRY_PARSE、TRY_CAST和TRY_CONVERT的共同特點:
1)即便轉換失敗也不會造成整個語句報錯,只會在無法轉換的情況下輸出NULL值;
TRY_PARSE:
TRY_PARSE是用於將字符串類型的數據轉換成時間或者數值類型的數據。它是一個基於.NET CLR Runtime的標量函數。語法是TRY_PARSE(<string/string column> AS <data_type> [USING <culture>])
下面做一個字符串轉時間的實驗:
SQL Server 版本:
Microsoft SQL Server 2014
Enterprise Edition (64-bit) on Windows NT 6.3 <X64>
SELECT TRY_PARSE('20150901' AS DATETIME), TRY_CAST('20150901' AS DATETIME), TRY_CONVERT(DATETIME,'20150901') SELECT TRY_PARSE('2015/09/01' AS DATETIME), TRY_CAST('2015/09/01' AS DATETIME), TRY_CONVERT(DATETIME,'2015/09/01') SELECT TRY_PARSE('2015/09/01 14:14:45' AS DATETIME), TRY_CAST('2015/09/01 14:14:45' AS DATETIME), TRY_CONVERT(DATETIME,'2015/09/01 14:14:45') SELECT TRY_PARSE('2015/09/01 14:14:45' AS DATETIME), TRY_CAST('2015/09/01 14:14:45' AS DATETIME), TRY_CONVERT(DATETIME,'2015/09/01 14:14:45') SELECT TRY_PARSE('2015/09/01 14:14:45+0001' AS DATETIME), TRY_CAST('2015/09/01 14:14:45+0001' AS DATETIME), TRY_CONVERT(DATETIME,'2015/09/01 14:14:45+0001')
上面代碼輸出的結果如下圖所示
可以看到TRY_PARSE在將純數字轉為DATETIME的情況下居然失效,這點讓我非常意外,而且我嘗試了DATE類型也是一樣的結果。
而如果加了像"-"或者"/"這樣的時間分隔符則三個函數都能轉換成功。
還有一點讓我驚訝的是TRY_CAST和TRY_CONVERT不支持帶有時區的轉換,而TRY_PARSE則可以。
而當我把第四行代碼的冒號修改成中文下面的冒號時則SQL Server辨認不出來。

TRY_CAST和TRY_CONVERT:
這一對更多是CAST和CONVERT這對函數的變體,語法上一樣,只是當無法成功轉換的時候是報錯或者輸出NULL值。
三者的區別總結如下:
1)TRY_PARSE只支持字符轉數值或者時間類型,而TRY_CAST和TRY_CONVERT支持更多的類型;
2)三者有一點比較好的就是對於字符的空格處理,只要空格在處在分割符號的前后像“2015/ 09/ 10”這樣是可以被成功處理的,但是如果空格隔開本身就是一個整體的數據值部分,則全部不能識別,像“2015/0 9/10”。
2)TRY_PARSE由於是CLR寫的函數,對於源數據的數據格式支持比較廣或者要求比較寬松,而TRY_CAST和TRY_CONVERT則要求比較嚴格。這點從上面的例子中,TRY_PARSE支持帶有時區的時間格式而其他兩個不支持就可以看出。而TRY_PARSE的支持范圍遠不止於此。
下面這個例子就證明了TRY_PARSE是僅最大的努力和可能去轉換數據,而后兩者則需要很嚴格數據格式
SELECT TRY_PARSE('Thursday, 19 Nov 2015' AS DATETIME) SELECT TRY_CONVERT(DATETIME, 'Thursday, 19 Nov 2015');

-------------------------------------- update 2015/12/09 ----------------------------------------------
TRY_PARSE和TRY_CAST在把字符轉換成數值這一功能上,TRY_PARSE在某種情況下要比TRY_CAST差。這里做個實驗。
SELECT Column1, TRY_CAST(Column1 AS FLOAT) AS TRY_CAST, TRY_CAST(REPLACE(Column1,',','') AS FLOAT) AS TRY_CAST_REMOVE_COMMA, TRY_PARSE(Column1 AS FLOAT) AS TRY_PARSE, TRY_PARSE(REPLACE(Column1,',','') AS FLOAT) AS TRY_PARSE_REMOVE_COMMA FROM OPENROWSET('Microsoft.ACE.OLEDB.12.0' ,'Excel 12.0 Xml;HDR=YES;IMEX=1;Database=D:\1.xlsx' ,'SELECT * FROM [sheet1$]');
上面語句的結果

我的源文件內容是這樣的:
| Column1 |
| 123,456 |
| 123456.789 |
| 123456 |
| 2,464 |
| 210,860 |
| ABC |
可以看到結果中對於第5行的轉換TRY_PARSE沒能把數字前后類似於空格的特殊字符忽略。這點上TRY_CAST應該說做得更加好。
