65.9K
CodeProject 正在变化。 阅读更多。
Home

纯 T-SQL 中的 URL 解码

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.33/5 (2投票s)

2007年1月25日

4分钟阅读

viewsIcon

82272

downloadIcon

180

如何在 T-SQL 中解码 URLEncoded URL。

引言

这是一篇关于如何在 T-SQL 中执行 URL 解码的短文。这是我最近需要做的事情,我努力在公共领域找到一个合适的解决方案,所以我决定自己编写一个。它完成的方式有些不寻常,因为表示编码字符的十六进制数并没有被视为数字,而是在整个过程中被视为字符串。我将首先完整地列出代码,因为它不是很长,然后我将逐步讲解,边讲边解释。

代码

CREATE FUNCTION fnURLDecode 
(
@input nvarchar(4000)
)  
RETURNS nvarchar(4000)
 
AS  
BEGIN 
 
declare @char nvarchar(2)
declare @asc nvarchar(2)
declare @asc2 nvarchar(2)

while (charindex('%', @input) > 0)
begin
 set @char=(select substring(@input, charindex('%', 
    @input) +1, 2))
 if (isnumeric(substring(@char, 1, 1)))>0
 begin
  set @asc=(select cast(substring(@char, 1, 1)
    as int))*16
 end
 else
 begin 
  set @asc=(select ascii(cast(substring(@char, 1, 1) 
    as char)))-55
  set @asc=(select @asc*16)
 end
 if (isnumeric(substring(@char, 2, 1)))>0
  set @asc=(select cast(@asc as int) + 
    (select cast(substring(@char, 2, 1) as int)))
 else
 begin 
  set @asc2=(select ascii(cast(substring(@char, 2, 1) 
    as char)))-55
  set @asc=(select cast(@asc as int) + 
    (select cast(@asc2 as int)))
 end
 set @input=
    (select substring(@input, 0, charindex('%', @input))) 
    + char(@asc) + (select substring(@input, charindex('%', 
    @input)+3, len(@input)))
end
return @input
END

正如你所看到的,这并不是有史以来最长的代码,但某些部分非常复杂,需要一些解释。我可以简化一些行,但超过一定程度后,您最终会为了简化而创建变量。我认为它大部分都足够清晰易懂了。

解释

让我们从头开始。我们从函数声明开始。这是一个 SQL Server 用户定义函数,它将一个字符串作为参数。它也返回一个字符串,一旦它被完全解码。然后我们定义三个变量。可能可以用更少的变量完成,但最后我用了三个。这些变量将存储 2 个字符组合。在第一种情况下,这些将是字符代码的十六进制部分,例如 "%20" 中的 "20"(空格)。在整个过程中,这些将被转换为它们所代表的字符。

从这里,我们进入一个 while 循环。循环条件基于 charindex 函数,具体来说,我们正在寻找下一个 "%" 字符的实例。在 URL 字符串中,此字符标识我们正在寻找的十六进制字符代码。该函数在进行过程中会调整输入字符串,因此首先处理第一个代码,更新字符串,当循环再次启动时,我们正在寻找第二个代码。最终,字符串中将不再有 "%" 的实例,循环将退出(当 charindex 函数的结果为 0 时)。

现在我们将 @char 设置为紧随当前 "%" 实例之后的 2 个字符。这是我们想要的密码。我们分别处理代码的每个字符。一个两位数的十六进制数可以通过将第一位数字乘以 16(只要它是数字的开头)并将第二位数字加到它来转换为十进制数(同样,只要它是数字)。这就是我们接下来要做的。首先,第一位数字是数字吗?如果是,我们应用上述公式,如果不是,我们做一些转换。

这部分更有趣。我没有尝试说服 SQL Server "A" 也可以是一个数字,而不仅仅是一个字符,我作弊了。 "A" 的 ASCII 码是 65。十六进制中的 "A" 代表数字 10。因此,十六进制数字 A-F 的十进制值只是它们的 ASCII 码减去 55。因此,如果我们当前查看的数字不是数字,我们应用此规则以获取其实际值。

举例来说,假设我们已经得到了以下字符代码:"%3F",这是"?"的代码。我们的例程寻找 "%",它就在开头。我们得到接下来的两个字符 "3F"。我们查看第一个字符,它是数字,所以我们将其乘以 16。到目前为止,这留下了 48,还需要添加 "F"。 "F" 不是数字,所以我们应用其他规则。F 的 ASCII 码是 70。我们从中减去 55 得到 15(F 的正确值)。我们将 15 加到我们的 48 中,得到 63。我们使用 chr 函数将此数字转换为其 ASCII 等价物,我们得到 "?",正如我们想要的。

该函数处理输入字符串,对每个编码字符应用上述推理。当它到达字符串的末尾时,它退出循环并返回解码后的字符串。

结论

我不相信这是将十六进制代码转换为 ASCII 字符的最佳方法,但它确实有效,并且在没有更好的方法的情况下,我将其提供出来供使用。由于该例程的工作方式,也可以从中剥离位,并将其用作通用十六进制->十进制转换器。反转该过程也应该允许您对字符进行编码,尽管需要编写一些代码来规定哪些字符需要转换。

此代码是在缺乏睡眠和一些莫名其妙的横向思维的产物。我希望它对某人有帮助。

© . All rights reserved.