鉴于网上有人问:SQLServer如何将UTF8转换为UNICODE,所以给出这个程序
当然参照本思路也可将UNICODE转换为UTF8。
网上有很多C#/C++的转换代码,当然都用到移位,但是由于SqlServer不支持移位,所以没有人给出T-SQL的转换代码。其实,左移位、右移位可以通过乘法、除法实现。
说明(应用场景):
比如你有一个图片,但是想给这个图片加上一点文字说明,又不想建立两个字段
这时,你可以把图片说明转换为UTF8的字节数组,然后与图片二进制数据合并,
同时存入一个SQLServer的VarBinary或Image字段中。
由于网络传输速度原因,你想在Select语句中仅仅想取出图片说明,不想取出图片数据,
这时,你可以按照你自己定义的存储规则,分解出图片说明字节。但是这些字节是保存为UTF8的,
而SQLServer仅仅支持UNICODE,因此,你就需要将UTF8字节转换为UNICODE字符串。
当然,1)你可以把图片说明在存入前就采用UNICODE编码而不采用UTF8,当然就不需要转换,可是如果以前的程序已经保存为UTF8了或者考虑到要和ASCII兼容,你就不得不采用UTF8(UTF8兼容ASCII,英文1字节,中文3字节;UNICODE是中英文都是双字节),你就不得不要转换了。
2)当然你也可以取出UTF8字节,在SL端转换为UNICODE,但是在SQL端转化好再传出来不是更为方便么?
---------------------------------------------------------------------------------
-- 将UTF8编码字节转换为UNICODE字符串
---------------------------------------------------------------------------------
-- UTF8(以下简称U8)--> UNICODE(以下简称UC)转换关系如下:
---------------------------------------------------------------------------------
-- 0)U8、UC与ASCII兼容,当字节高位为0时,是英文无需转换,为1时,是汉字需要转换
-- 1)U8一个字节一英文,三字节一汉字(对纯英文来说,存储无浪费,所以老外很喜欢)
-- UC二个字节一英文,二字节一汉字(对存英文来说,存储有浪费,所以老外不喜欢)
-- 2)UC的第1个字节的1、2、3、4位,对应于U8的第1个字节的5、6、7、8位
-- 3)UC的第1个字节的5、6、7、8位,对应于U8的第2个字节的3、4、5、6位
-- 4)UC的第2个字节的1、2、3、4位,对应于U8的第2个字节的7、8位及第3个字节的第3、4位
-- 5)UC的第2个字节的5、6、7、8位,对应于U8的第3个字节的5、6、7、8位
---------------------------------------------------------------------------------
ALTER FUNCTION DBO.GetUCStr (@U8VarBin VARBINARY(MAX))
RETURNS NVARCHAR(MAX)
AS
BEGIN
DECLARE @Rlt NVARCHAR(MAX)
SET @Rlt = NULL
DECLARE @I INT,
@N INT
SET @I = 1
SET @N = DATALENGTH(@U8VarBin)
WHILE @I <= @N BEGIN
DECLARE @B TINYINT
SET @B = CAST(SUBSTRING(@U8VarBin, @I, 1) AS TINYINT)
IF (@B & 128) <= 0 BEGIN
SET @Rlt = ISNULL(@Rlt, '') + NCHAR(CAST(@B AS INT))
SET @I = @I + 1
END
ELSE BEGIN
IF (@I + 2) <= @N BEGIN
DECLARE @U8B1 TINYINT,
@U8B2 TINYINT,
@U8B3 TINYINT
SET @U8B1 = CAST(SUBSTRING(@U8VarBin, @I + 0, 1) AS TINYINT)
SET @U8B2 = CAST(SUBSTRING(@U8VarBin, @I + 1, 1) AS TINYINT)
SET @U8B3 = CAST(SUBSTRING(@U8VarBin, @I + 2, 1) AS TINYINT)
DECLARE @UCB1 TINYINT,
@UCB2 TINYINT
SET @UCB1 = 0
SET @UCB1 = (@UCB1) | ((@U8B1 & 15) * 16)
SET @UCB1 = (@UCB1) | ((@U8B2 & 60) / 4)
SET @UCB2 = 0
SET @UCB2 = (@UCB2) | ((@U8B2 & 3) * 64)
SET @UCB2 = (@UCB2) | ((@U8B3 & 48) * 1)
SET @UCB2 = (@UCB2) | ((@U8B3 & 15) * 1)
SET @Rlt = ISNULL(@Rlt, '') + NCHAR(@UCB1 * 256 + @UCB2)
END
SET @I = @I + 3
END
END
RETURN @Rlt
END