我在php中有一个用urlencode编码的列url。我希望做出这样的选择 SELECT some_mix_of_functions(...)AS Decoded FROM table
替换不是一个好的解决方案,因为我必须手动添加所有解码。获得欲望结果的任何其他解决方案?
答案 0 :(得分:10)
是的,你可以:
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')
或者您可以使用上述函数体中的函数和子查询的混合。
这不会处理'+'字符(代表空白),但我想添加它很容易(如果你需要的话)。
此外,这假设utf-8编码为非ascii字符,但如果需要,您可以用自己的编码替换'UTF8'。
应该注意的是,上面的代码依赖于未记录的postgresql特性,即regexp_matches函数的结果按照它们在原始字符串中出现的顺序进行处理(这是自然的,但未在docs中指定)。
正如Pablo Santa Cruz所说,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');
答案 1 :(得分:0)
没有开箱即用。但是你可以创建一个pl / perl函数来包装perl等价物。 (或pl/php function)。