zoukankan      html  css  js  c++  java
  • SqlServer Base64解码中文

    最近在做一个和拥有TurboCRM相关的项目,其中需要取出客户信息的联系人字段,经过查看,这个字段在存入时用Base64加密过了

    这个功能在应用层实现是很方便的,但是由于一些特殊原因,只能放到SqlServer里面进行解码,语句比较简单,但是花了很长时间,特此记录以避坑

    1.创建Base64解码函数

    CREATE FUNCTION [dbo].[base64_decode]
    (
    @encoded_text varchar(max)
    )
    RETURNS varbinary(max)
    AS
    BEGIN
    DECLARE
        @output varbinary(max),
        @block_start int,
        @encoded_length int,
        @decoded_length int,
        @mapr binary(122)
    IF LEN(@encoded_text) & 3 > 0
        OR @encoded_text LIKE '%[^ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=]%' COLLATE Latin1_General_Bin
        RETURN NULL
    SET @output = 0x
    -- The nth byte of @mapr contains the base64 value of the character with an ASCII value of n.
    -- eg. 65th byte = 0x00 = 0 = value of 'A'
    SET @mapr =
              0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF -- 1-33
            + 0xFFFFFFFFFFFFFFFFFFFF3EFFFFFF3F3435363738393A3B3C3DFFFFFF00FFFFFF -- 33-64
            + 0x000102030405060708090A0B0C0D0E0F10111213141516171819FFFFFFFFFFFF -- 65-96
            + 0x1A1B1C1D1E1F202122232425262728292A2B2C2D2E2F30313233 -- 97-122
    --get the number of blocks to be decoded
    SET @encoded_length = LEN(@encoded_text)
    SET @decoded_length = @encoded_length / 4 * 3
    --for each block
    SET @block_start = 1
    WHILE @block_start < @encoded_length
    BEGIN
        --decode the block and add to output
        --BINARY values between 1 and 4 bytes can be implicitly cast to INT
        SET @output = @output +
            CAST(CAST(
                  SUBSTRING(@mapr, ASCII(SUBSTRING(@encoded_text, @block_start    , 1)), 1) * 262144
                + SUBSTRING(@mapr, ASCII(SUBSTRING(@encoded_text, @block_start + 1, 1)), 1) * 4096
                + SUBSTRING(@mapr, ASCII(SUBSTRING(@encoded_text, @block_start + 2, 1)), 1) * 64
                + SUBSTRING(@mapr, ASCII(SUBSTRING(@encoded_text, @block_start + 3, 1)), 1)
            AS int) AS binary(3))
        SET @block_start = @block_start + 4
    END
    IF RIGHT(@encoded_text, 2) = '=='
        SET @decoded_length = @decoded_length - 2
    ELSE IF RIGHT(@encoded_text, 1) = '='
        SET @decoded_length = @decoded_length - 1
    RETURN SUBSTRING(@output, 1, @decoded_length)
    END

    2.创建UTF8转换函数,转换后的字符为UTF8,如果直接转换会造成乱码的情况

    CREATE FUNCTION [dbo].[utf8_to_ucs2](
    @utf8 varbinary(max)
    )
    RETURNS varbinary(max)
    AS
    BEGIN
        DECLARE
            @output varbinary(max),
            @i int,
            @next int,
            @code int,
            @tmp varbinary(1)
        SET @output = 0x
        SET @i = 1
        SET @next = 0
        WHILE 1 = 1
        BEGIN
            SET @tmp = SUBSTRING(@utf8,@i,1)
            IF @tmp = 0x
                BREAK
            IF @tmp BETWEEN 0x01 AND 0x7F
                SET @output = @output + @tmp + 0x00
            ELSE IF @tmp BETWEEN 0xC0 AND 0xDF
            BEGIN
                SET @code = (CAST(@tmp AS int) & 0x1F) * 64
                SET @next = 1
            END
            ELSE IF @tmp BETWEEN 0xE0 AND 0xEF
            BEGIN
                SET @code = (CAST(@tmp AS int) & 0x0F) * 4096
                SET @next = 2
            END
            ELSE IF @tmp BETWEEN 0x80 AND 0xBF AND @next IN (1,2)
            BEGIN
                IF @next = 1
                BEGIN
                    SET @code = @code + (CAST(@tmp AS int) & 0x3F)
                    SET @output = @output + CAST(NCHAR(@code) AS binary(2))
                END
                IF @next = 2
                    SET @code = @code + (CAST(@tmp AS int) & 0x3F) * 64
                SET @next = @next - 1
            END
            ELSE
                RETURN NULL
            SET @i = @i + 1
        END
        RETURN @output
    END

    3.查询语句使用方式如下,此处要注意如果是中文必须使用NVARCHAR否则会乱码

    SELECT CONVERT(nvarchar(max), dbo.utf8_to_ucs2(dbo.base64_decode('6Zm25oC7')))
  • 相关阅读:
    nyoj 202红黑树 (搜索)
    POJ 3281 Dining(最大流)
    nyoj-488 素数环 +nyoj -32 组合数 (搜索)
    LeetCode100:Same Tree
    LeetCode283:Move Zeros
    Leetcode226:Invert Binary Tree
    LeetCode258:Add Digits
    Leetcode237:Delete Node in a Linked List
    LeetCode7:Reverse Integer
    LeetCode292:Nim Game
  • 原文地址:https://www.cnblogs.com/liuyi2614/p/9002570.html
Copyright © 2011-2022 走看看