使用 T-SQL 实现 base64 解码

IF OBJECT_ID(N'dbo.f_base64_decode'IS NOT NULL
    
DROP FUNCTION dbo.f_base64_decode;
GO

/*-- == base64 解码=================================
    在SQL Server 中,使用FOR XML 生成xml 实例时,binary 数据
使用base64 编码,而解释xml 的时候,却没有相应的解码方法。
    使用此函数可以解决这个问题
   
    Base64 编码把个位字节(*8=24)转化为个位的字节(*6=24)
之后在位的前面补两个,形成位一个字节的形式。用下面的个字符重新
表示:“ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/”
    如果输入的数据的长度不是的倍数,则编码结果的不足部分用等号“=”
补足。
 
---------------------------------------------------------
-- 调用示例
 
    SELECT -- 还原成字符串
       v1 = CONVERT(varchar(max), v1),
       v2 = CONVERT(nvarchar(max), v2)
    FROM(
       SELECT  -- 解码base64 编码
           v1 = dbo.f_base64_decode(v1),
           v2 = dbo.f_base64_decode(v2)
       FROM(  -- 通过for xml 生成base64 编码
           SELECT
             v1 = (SELECT CONVERT(varbinary(max), 'base64 test') FOR XML PATH(''), TYPE).value('/', 'nvarchar(max)'),
              v2 = (SELECT CONVERT(varbinary(max), N'base64 解码测试') FOR XML PATH(''), TYPE).value('/', 'nvarchar(max)')
       )DATA
    )A
 
---------------------------------------------------------
-- 环境要求
 
适用于sql server 2005 或者更高的版本

-- ==== 邹建.02(引用请保留此信息) =============== 
*/
CREATE FUNCTION dbo.f_base64_decode(
    
@input varchar(max)
)
RETURNS varbinary(max)
AS
BEGIN
    
DECLARE
       
@base64 char(64),
       
@pos int,
       
@len int,
       
@output varbinary(max);
 
    
SELECT
       
@base64 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/',
       
@pos = 1,
       
@len = LEN(@input),
       
@output = 0x;
 
    
IF @input = ''
       
RETURN 0x;
 
    
IF @len % 4 > 0 OR @len IS NULL
       
RETURN NULL;
      
    
WHILE @pos < @len
    
BEGIN
       
SELECT
           
@output = @output
              
+ CONVERT(binary(1), ((v1 & 63* 4 ) | ((v2 & 48/ 16))
              
+ CONVERT(binary(1), ((v2 & 15* 16| ((v3 & 60/ 4 ))
              
+ CONVERT(binary(1), ((v3 & 3 ) * 64| ((v4 & 63/ 1 )),
           
@pos = @pos + 4
       
FROM(
           
SELECT
              v1 
= CHARINDEX(SUBSTRING(@input@pos + 01) COLLATE Chinese_PRC_BIN, @base64- 1,
              v2 
= CHARINDEX(SUBSTRING(@input@pos + 11) COLLATE Chinese_PRC_BIN, @base64- 1,
              v3 
= CHARINDEX(SUBSTRING(@input@pos + 21) COLLATE Chinese_PRC_BIN, @base64- 1,
              v4 
= CHARINDEX(SUBSTRING(@input@pos + 31) COLLATE Chinese_PRC_BIN, @base64- 1     
       )A;
    
END;
 
    
RETURN(SUBSTRING(@output1@len / 4 * 3 - 3 + CHARINDEX('='RIGHT(@input2+ '=')));
END;
GO


posted @ 2010-02-07 16:56  wenanry  阅读(3766)  评论(1编辑  收藏  举报