所以這兩天坎尼又重新測了一下問題發生的原因
先講一下這次的問題所在
SqlCommand.Parameters.Add 有個多載是可以傳入參數值的 size
但在 varchar 的狀態下,傳入中文並不會把值鎖定在 10,以至於系統拋出了例外
先來看範例,首先是資料表定義,有個 varchar(10) 的欄位
接著是可正常運作的範例
相信大家都知道,中文字在 varchar 中會佔 2 單位
所以6個中文字以上的字串,是無法新增至上面所定義的欄位表
當時坎尼就是遇到要把中文字存到 varchar 的欄位中
但很明顯的,size參數完全起不了作用
而且同事還說要不要用 String.SubString 的方法把資料截斷啊?
正確的做法應該是要先轉成 byte[] ,再將資料截斷送入
原本的 "無敵鐵金鋼2" 就被截斷後再送入資料庫中
但這個解法只限於傳入的值皆為 2bytes 的字
一但需截斷的資料中有1byte的字,就可能發生中文字被腰斬的情況
上面談了這麼多
是不是要證明 SqlCommand.Parameters.Add 的第3個 size 參數沒有用呢?
當然不是,它當然有用,只是在上面範例中不適合
其實只要把字串改成全為英文,Parameter就會自動把超過的字串切掉
上述例子中沒有作用的原因為:
中文字才6個,還未達到Length=10的瓶頸
但又因為中文字每個字代表2bytes,所以早就超過資料表裡的限制
字串切割會以字的數目,而非字所佔的容量
「一二3四五」和「12345」同樣是算 5 個字
用 String.Substring(0,6) 即會拋出 index 不符的例外
但其實上述的範例真正的解決方式為...
應將有可能出現中文字的欄位設為 nvarchar,且前端要針對輸入的字作控管
最後補充一下小小的發現
上面 Table 裡的 ID 值是用遞增方式,但卻少了 2,難道是坎尼自己偷刪嗎?
其實是上述的測試中,坎尼故意傳了大於欄位長度的值進去,因此在 Sql 方面出現例外
不過遞增值的 flag 似乎自動加一了? 所以才會跳過該數字