最近在處理客戶的FTP下來的資料,出現如題的問題
txt文本裡有如下記錄:
廣東省某某某某某某某某某公司-IC卡,100,100
廣東省某某某某某某某某公司-IC?100,100
問題,下面這行的分隔符不見了,造成數據無法導入本地SQL2000
這個字段類型是varchar(30),這是最近的文檔資料,但我發現導出的資料有超過30長度的。證明這個字段現在只是修改了文檔資料為30長度,而數據庫必然是大於30的,只是從其它工單表裡轉入資料時作了切斷來滿足現在文檔的要求,否則也不可能完整存放長度大於30的字符串(第一行)。
而這個切斷就出現了問題,其實我們看到的問號,並非是英文的問號,而是半個漢字與逗號的結合造成的亂碼。
所以總結一下就是:數據長度剛好30,而且英文字符的數量是奇數,並且以漢字結尾。
當然,如果是以英文結束並切斷英文部分,是不會造成這個問題的;如果英文字符數量是偶數也沒問題。
徹底解決方法:
這個問題的澈底解決方法是不要作切斷,否則肯定會出現或多或少的問題。而至於要完整的切斷一個中文,在處理效率上不現實。當然這是程序的問題了。
折衷的解決方法:
1. 本地文本替換問號為逗號,但不一定保險。因為目前除問號問題外,還出現了數據折行顯示,甚至跳過幾行等問題,其歸根結底是中文切字造成不可見字符造成的。而且這個沒什麼規律。
因為我們雖然在notepad裡看到的是問號"?",並且可以替換,但是編程來替換就不行,因為末字符是ascii>127的,而且你無法判斷是半個字符,因為漢字就是兩個半個字符組合而成,除非用我上面用黑體顯示的那個規律來判斷之。(與notepad裡能看到問號是兩碼事)
2. 本地表加寬成varchar(40),導出是增加一個“A-Z”的字符,如果後面有半個字符則結合成一個字或者問號,從而不會與逗號結合。如果沒有半個字符則顯示出這個英文,影響也不大。
導出時選擇用一條sql語句來篩選:select id,name=name+'A',price from tab_name where 1=1
我在sql2000裡測試增加一個'A':IP專?3269334變成了: IP專蟌,3269334
如果末尾加英文的空格,顯然比較貼切,有半個字符的顯示為問號,但不吃掉逗號,而正常的記錄只是多一個空格出來,完全不影響實際上使用。(推薦)
select id,name=name+' ',price from tab_name where 1=1
IP專?3269334 變成了: IP專?,3269334
當然聰明的人能想到,先在末尾添加一個字符,再用left(name,len(name)-1)來處理也是可以的,因為left是基於一個完整的字符,英文算一個,漢字也算一個。
select id,name=left(name+'A ',len(name+'A')-1),price from tab_name where 1=1
(結果非常完美)
當然還有人認為不用添加一個字符,直接切掉末尾字符,當然沒問題的字段也會被切掉一個,當然不可以。
3. 判斷長度為30而且英文字符數為奇數,則切斷末尾的半個漢字。這個方法太費勁。而且這種方法不是數據庫維護人員能做到的。(簡直沒必要費這個勁)
4. 在導出時用sql語句把字段轉換成nvarchar(30),我在sql2000裡測試ok.
select id,name=cast(name as nvarchar(30)),price from tab_name where 1=1
即說2,4的方法是可行的。windowxp+sql2000裡我測試過。其它DBsys和OS未作測試。