Да, вы можете:
CREATE OR REPLACE FUNCTION decode_url_part(p varchar) RETURNS varchar AS $$
SELECT convert_from(CAST(E'\\x' || string_agg(CASE WHEN length(r.m[1]) = 1 THEN encode(convert_to(r.m[1], 'SQL_ASCII'), 'hex') ELSE substring(r.m[1] from 2 for 2) END, '') AS bytea), 'UTF8')
FROM regexp_matches($1, '%[0-9a-f][0-9a-f]|.', 'gi') AS r(m);
$$ LANGUAGE SQL IMMUTABLE STRICT;
Это создает функцию decode_url_part
, тогда вы можете использовать ее так:
SELECT decode_url_part('your%20urlencoded%20string')
Или вы можете просто использовать сочетание функций и подзапросов из тела вышеуказанной функции.
Это не обрабатывает символы '+' (представляющие пробелы), но я думаю, добавить это довольно легко (если вам это когда-нибудь понадобится).
Также предполагается, что для символов, отличных от ascii, используется кодировка utf-8, но вы можете заменить «UTF8» на собственную кодировку, если хотите.
Следует отметить, что приведенный выше код использует недокументированную функцию postgresql, а именно то, что результаты функции regexp_matches обрабатываются в том порядке, в котором они встречаются в исходной строке (что естественно, но не указано в документах).
Как отмечает Пабло Санта-Крус, string_agg - это агрегатная функция PostgreSQL 9.0. Эквивалентный код ниже не использует его (надеюсь, он работает для 8.x):
SELECT convert_from(CAST(E'\\x' || array_to_string(ARRAY(
SELECT CASE WHEN length(r.m[1]) = 1 THEN encode(convert_to(r.m[1], 'SQL_ASCII'), 'hex') ELSE substring(r.m[1] from 2 for 2) END
FROM regexp_matches($1, '%[0-9a-f][0-9a-f]|.', 'gi') AS r(m)
), '') AS bytea), 'UTF8');