在Redshift中将字符串中的所有十六进制转换为其char值

Ngh*_* Le 2 amazon-redshift

在Redshift中,我正在尝试像这样转换字符串:

http%3A%2F%2Fwww.amazon.com%2FTest%3Fname%3DGary%26Bob
Run Code Online (Sandbox Code Playgroud)

看起来像这样:

http://www.amazon.com/Test?name=Gary&Bob
Run Code Online (Sandbox Code Playgroud)

基本上,我需要将字符串中的所有十六进制转换为其char值。我能想到的唯一方法是使用正则表达式函数。我试图用两种不同的方式来做到这一点,并收到两种的错误消息:

SELECT REGEXP_REPLACE(hex_string, '%([[:xdigit:]][[:xdigit:]])', CHR(x'\\1'::int))
ERROR: 22P02: "\" is not a valid hexadecimal digit

SELECT REGEXP_REPLACE(hex_string, '%([[:xdigit:]][[:xdigit:]])',CHR(STRTOL('0x'||'\\1', 16)::int))
ERROR: 22023: The input 0x\1 is not valid to be converted to base 16
Run Code Online (Sandbox Code Playgroud)

CHR和STRTOL函数本身起作用。例如:

SELECT CHR(x'3A'::int)
SELECT CHR(STRTOL('0x3A', 16)::int)
Run Code Online (Sandbox Code Playgroud)

都返回

:
Run Code Online (Sandbox Code Playgroud)

而且,如果我使用不同的功能(CHR和STRTOL除外)运行相同的模式,则它会起作用:

REGEXP_REPLACE(hex_string, '%([[:xdigit:]][[:xdigit:]])', LOWER('{H}'||'\\1'||'{/H}'))
Run Code Online (Sandbox Code Playgroud)

退货

http{h}3A{/h}{h}2F{/h}{h}2F{/h}www.amazon.com{h}2F{/h}Test{h}3F{/h}name{h}3D{/h}Gary{h}26{/h}Bob
Run Code Online (Sandbox Code Playgroud)

但是由于某些原因,这些功能无法识别正则表达式匹配组。

关于如何执行此操作的任何提示?

我猜另一种解决方案是对所有特殊的十六进制字符使用嵌套的REPLACE()函数,但这可能是最后的选择。

hid*_*bit 5

您要执行的操作称为“ URL解码”。

当前没有内置函数可以执行此操作,但是您可以创建一个自定义的用户定义函数(确保您具有所需的特权):

CREATE FUNCTION urldecode(url VARCHAR)
RETURNS varchar
IMMUTABLE AS $$
  import urllib
  return urllib.unquote(url).decode('utf8')  # or 'latin-1', depending on how the text is encoded
$$ LANGUAGE plpythonu;
Run Code Online (Sandbox Code Playgroud)

查询示例:

SELECT urldecode('http%3A%2F%2Fwww.amazon.com%2FTest%3Fname%3DGary%26Bob');
Run Code Online (Sandbox Code Playgroud)

结果:

http://www.amazon.com/Test?name=Gary&Bob
Run Code Online (Sandbox Code Playgroud)