[轉載]SQL SERVER 自動轉換害了你

[轉載]SQL SERVER 自動轉換害了你

引用於  http://www.cnblogs.com/skylaugh/archive/2007/03/05/664031.html

SQLServer有很強的格式自動轉換功能,但是他不是萬能的,有些時候也是轉換不了的,而且出現錯誤我們很難查找,因為我們有些時候是可以的,有些時候又出現問題。正確之時都是SQLServer格式轉換範圍內的,那些超出界限的,就會出現錯誤,而出現錯誤的時候,我們的程序員就會陷入一個誤區:檢查別的地方代碼,而且為此浪費很多的時間,貽誤了工程進度,對項目來說是有害的,對自己來說,更是有害的。下面有個例子,我們可以參考一下,借此說明此問題。

問題陳述:
有一天,執行
SELECT * FROM XXX_ORIGINAL_20031205
where msgid=62010388000012

語句,結果SQL Server報告出錯:「將數據類型 varchar 轉換為 numeric 時出錯。」

這是什麼意思呢?

Msgid這個字段的類型是:varchar(30)。

原因分析:
不是SQL Server突然不能從數字自動轉換為字符串,而是單單對這個字段的數值有問題,這也和這個字段中實際已存儲的字符串有關。

你看,我執行這個SQL語句是沒有問題,可以自動轉換:

SELECT * FROM XXXX_ORIGINAL_20031205
where recordid=62010388000012

recordid這個字段的類型也是:varchar(30)。
這為什麼就可以呢?

為什麼?

這是因為msgid字段的真實數值是類似於這樣的字符串「12051113280101053509」,由於你的SQL命令中要求拿字符串跟我們提供的這個數字62010388000012匹配,所以SQLServer默認要把這麼多個「12051113280101053509」先統統轉換為數字,再去跟62010388000012匹配。

(首先這就涉及到一個效率問題,轉換這麼多msgid成為數字,再跟你的數字匹配,將是一個多麼大的浪費啊)

當然,這回SQLServer轉不過來了,因為「12051113280101053509」換為數字實在太大了,超出了範圍,所以你看SQLServer於是乎報告「將數據類型 varchar 轉換為 numeric 時出錯」,他指的就是把歷史數據「12051113280101053509」這個varchar(30)轉成numeric不行,而不是把你SQL腳本傳遞的參數62010388000012轉換失敗。

讓我們看看另一種形式的錯誤,就更清楚了:

我們執行

SELECT * FROM XXXX_ORIGINAL_20031205
where msgid=120

命令就會得到錯誤:

varchar 值 '12050003010101026986' 的轉換溢出了 int 列。超出了最大整數值。

這個錯誤,是不是很清楚地表明了SQLServer在幫你執行SQL命令時背後所作的事情?

他試圖幫你主動把記錄中的這個字段轉換成你在SQL命令中指明的那個數據類型。

總結:

很多時候,我們懶得去看某個字段到底是什麼類型,是char,還是tinyint,還是bool,還是varchar,我們就隨便寫一個數字,讓聰明的SQL Server自己去判斷該轉成什麼。

再次我將聰明的SQL Server自動轉換給我們帶來的害處簡單羅列:

1、增加出錯次數,而且出現錯誤容易讓我們陷入誤區,讓我們的程序不夠健壯。
2、自動轉換會增加SQL的執行時間,讓我們的程序沒有效率。
3、給我們程序帶來無限隱患,為後期的功能延伸帶來麻煩

建議:

不積硅步何以至千里,千里長堤潰於蟻穴。希望程序員兄弟們以次為鑒,自己勤快一點,養成一個好的習慣,在錯誤產生之前搞定他。

請自己判斷好格式,然後將數據傳給SQLServer,因為相信機器,不如相信自己。