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')))

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM