我正在尝试将PostgreSQL文本数组转换为一个值,其中每个值都被替换为每个空格被每边的字符包围的值。换句话说,我正在尝试对文本数组中的每个值应用trim()
和regexp_replace()
。这些都是在数据库函数中完成的(除此之外)。
CREATE OR REPLACE FUNCTION manipulate_array(multiplevalues text[])
RETURNS text[] AS
$BODY$
DECLARE
singlevalue text;
BEGIN
FOREACH singlevalue IN ARRAY multiplevalues LOOP
SELECT trim(regexp_replace(singlevalue, '\s+', ' ', 'g')) INTO singlevalue;
END LOOP;
RETURN multiplevalues;
END;
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
ALTER FUNCTION manipulate_array(multiplevalues text[]) OWNER TO username;
不幸的是,当我用multiplevalues = '{" red ", " blue ", " Ye llow "}'
作为参数之一调用函数时,返回的值是完全相同的文本数组。如何将'{"red", "blue", "yellow"}'
作为返回值?
我一直在盯着trim()
,regexp_replace()
和FOREACH
循环的定义,我可能只需要别人检查。
答案 0 :(得分:1)
您的代码永远不会更改multiplevalues
数组。它只是改变了每个元素,然后抛弃了新的价值。
您需要一个变量,您可以将结果汇总到:
CREATE OR REPLACE FUNCTION manipulate_array(multiplevalues text[])
RETURNS text[] AS
$BODY$
DECLARE
singlevalue text;
l_result text[] := '{}'::text[]; -- initialize with an empty array
BEGIN
FOREACH singlevalue IN ARRAY multiplevalues LOOP
SELECT trim(regexp_replace(singlevalue, '\s+', ' ', 'g')) INTO singlevalue;
l_result := l_result || singlevalue; -- append to the result
END LOOP;
RETURN l_result; -- return the new array, not the old one
END;
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
但是使用unfst和array_agg以及普通的SQL函数(而不是PL / pgSQL)可以做得更简单
首先需要取消数组,修剪值以及返回数组的聚合。
我不确定我理解你要做什么,但这会修剪数组中的所有值并返回一个新值:
create function trim_all(p_values text[])
returns text[]
as
$$
select array_agg(trim(regexp_replace(t.v, '\s+', ' ', 'g')) order by t.nr)
from unnest(p_values) with ordinality as t(v, nr);
$$
language sql;
答案 1 :(得分:1)
还有一些改进:
CREATE FUNCTION trim_all1(text[])
RETURNS text[] AS
$func$
SELECT ARRAY (
SELECT regexp_replace(trim(elem), '\s+', ' ', 'g')
FROM unnest($1) elem
)
$func$ LANGUAGE sql IMMUTABLE;
在昂贵的trim()
之前应用便宜的regexp_replace()
通常会更快。
简化array constructor比array_agg()
聚合单个数组更快。
IMMUTABLE
(因为它是)。在某些情况下更快,可用于索引等。
如果您专门处理普通空格字符,请进一步简化:
CREATE FUNCTION trim_all2(text[])
RETURNS text[] AS
$func$
SELECT ARRAY (
SELECT regexp_replace(trim(elem), ' +', ' ', 'g')
FROM unnest($1) elem
)
$func$ LANGUAGE sql IMMUTABLE;
正则表达式相对昂贵。如果您进一步知道连续空格字符不超过 n ,则可以使用简单的replace()
。几个串口通话仍然更便宜。对于最大值连续8个空格:
CREATE OR REPLACE FUNCTION trim_all3(text[])
RETURNS text[] AS
$func$
SELECT ARRAY (
SELECT replace(replace(replace(
trim(elem)
, ' ', ' ') -- 5
, ' ' , ' ') -- 3
, ' ' , ' ') -- 2
FROM unnest($1) elem
)
$func$ LANGUAGE sql IMMUTABLE;
在我对pg 9.5的测试中,每个测试都比前一个版本快,最后一个版本的速度是@a_horse's function的两倍。
相关:
SQL标准允许任何订单而不显式ORDER BY
。但是在这个简单的安排中,Postgres将保持元素的原始顺序。
在这里阅读更多内容: