none
SL通常使用UTF8,而SQL使用UNICODE,所以发一个SQL2000中UTF8转换为UNICODE的程序给大家参考 RRS feed

  • 常规讨论

  • 鉴于网上有人问: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

    2010年3月27日 17:34

全部回复