SQL筆記:SUBSTRING之錯誤訊息誤導?(其實是自己誤解)
今早某隻程式突然報錯,錯誤是來自SQL的標準錯誤訊息「將 nvarchar 值 'XX' 轉換成資料類型 int 時,轉換失敗。」,顯而易見的就是可能發生轉型時的失敗,經過追查後才發現案情並不單純,因此將這個問題記錄在此供給日後參考。
錯誤訊息的起始
以下是報錯的SQL指令,很單純:
SELECT
*
FROM
TestView
WHERE
SUBSTRING(cCode, 5, 1) <> 5
吐出錯誤訊息如下,很顯然的就是第五個字元出現不可自動轉型成數字的問題,理論上只要修正成字元比對模式「'5'」即可。
將 nvarchar 值 'X' 轉換成資料類型 int 時,轉換失敗。
但,調查下去發現案情並不單純...
檢視表VIEW中,並沒有那筆資料?
把檢視表中「所有資料」查找一次,發現根本沒有錯誤訊息指出的'X'字元,阿是在報錯三小?
SELECT
*
FROM
TestView
iSN cCode bState
1 12345678 1
2 22345678 1
4 42345678 1
經過東翻西找後,確定並不是語法問題而是在SQL自己本身查詢的機制,以下是TestView的產生指令,從指令中可以發現是以JOIN的方式來生成:
SELECT
dbo.TestTable.iSN, dbo.TestTable.cCode, dbo.TestState.bState
FROM
dbo.TestTable
INNER JOIN
dbo.TestState
ON
dbo.TestTable.iSN = dbo.TestState.iSN
WHERE
dbo.TestState.bState = 1
再往下追TestTable資料表,就發現兇手了:
SELECT
*
FROM
TestTable
iSN cCode
1 12345678
2 22345678
3 3234X678 << 兇手在此
4 42345678
心得
若檢視表有使用到JOIN指令,當我們針對檢視表進行WHERE查詢時,SQL的動作未必如我們想像中是「先針對」VIEW產生「結果」,再基於這個結果去進行查詢動作。我們可以從下圖「顯示估計執行計畫」中看到,SQL的確把SUBSTRING的指令放到TestTable中查找。