问:
由于从其它数据库中导入的数据存在半个汉字的问题,所以希望能在查询语句中将这半个汉字处理掉,请问怎样才能解决这个问题?
答:
“汉字是由两个字节存储的,每个字节的数值都>127。所以上面问题的解决方案就是:把字符串按字节顺序截取,当出现第一个字节是>127,但是后面一个字节是<127的这种情况,选择丢掉。
接下来,我们来明确技术细节:
(1) 在SQL Server中有很多字符串相关的操作函数,但是直接去操作包含了汉字的字符串,会有点问题。说明如下:LEN计算长度的时候,会把汉字和英文字符都看成长度一样的;substring也是这样,ascii是返回第一个字节的ASCII 码。
Example: select len('你好a'), substring('你好a',1,1),ascii('你') 结果是 ----------- ---- - ---- 3 你 196
一定要把字符串要转换成varbinary来处理,才可以。
(2) SQL Server中,如何把ASCII码组合成汉字,就是把高字节和底字节分别转成字符再拼接起来。如char(210)+char(166)就是姚这个汉字。
再明确了上面的技术细节后,接下来就可以解决问题了。我通过编写一个函数来解决问题。
create function fn_TruncSemiHanzi (@str varchar(4000)) returns varchar(8000) as begin declare @sTmp varchar(8000),@i int, @itmp int,@itmp2 int ,@stmp2 varchar(2) select @sTmp=' select @i=1 while @i<=len(@str) begin select @itmp=convert(int,substring (convert(varbinary,substring(@str ,@i,1)),1,1)) --截取一个字节 if @itmp>127 begin --大于127检查后面一个字节 select @itmp2=convert(int,substring (convert(varbinary,substring(@str ,@i,1)),2,1)) if @itmp2>127 begin select @stmp2=char(@itmp)+char(@itmp2) --是一个完整的汉字 end else begin select @stmp2=char(@itmp2) --丢弃半个汉字 end end else begin select @sTmp2=char(@itmp) end select @sTmp=@sTmp+@stmp2 select @i=@i+1 end return @stmp end
测试如下:
DECLARE @str varchar(4000) -- 设置参数值 -- 设置参数值 --带有半个汉字,是你这个汉字的前面一部分 select @str='b'+char(convert (int,substring(convert(varbinary,'你'),1,1)))+'a你' select @str 带有半个汉字, dbo.fn_TruncSemiHanzi(@str) 去掉半个汉字 带有半个汉字 长度 去掉半个汉字 长度 ------------------ ----------- ---------- b腶你 3 ba你 3
我们还可以发现这样一个有趣的现象,由于我是截了半个汉字出来,结果你的前半个汉字的字符和后面一个英文字母a 组合,成了一个怪怪的字符腶。
总结:
通过这个问题的解决,大家可以了解汉字在SQL Server2000中存储和处理的基本方法,像如何区分一个字符串中是否包含了汉字,和分离字符串中中文和英文都可以套用本文中方法。
本文中测试的环境是Win2000 Server(中文)+SQL Server 2000(中文),英文环境下没有测试,如有问题,欢迎大家指正。