1

我有一张这样结构的桌子......

the_geom 数据

geom1    data1+3000||data2+1000||data3+222

geom2    data1+500||data2+900||data3+22232

我想创建一个按用户请求返回记录的函数。

Example: for data2, retrieve geom1,1000 and geom2, 900

直到现在我创建了这个函数(见下文),它工作得很好,但我面临一个参数替换问题......(你可以看到我无法用 'data2' 替换 $1 ......但是是的,我可以使用 $1之后

regexp_matches(t::text, E'(data2[\+])([0-9]+)'::text)::text)[2]::integer

我的功能

create or replace function get_counts(taxa varchar(100))

returns setof record

as $$

SELECT t2.counter,t2.the_geom

FROM  (

   SELECT (regexp_matches(t.data::text, E'(data2[\+])([0-9]+)'::text)::text)[2]::integer as counter,the_geom

   from (select the_geom,data from simple_inpn2 where data ~ $1::text) as t

    ) t2

   $$
 language sql;

SELECT get_counts('data2') will work **but we should be able to make this substitution**:

regexp_matches(t::text, E'($1... instead of E'(data2....

我认为它更多的是语法问题,因为函数执行没有错误,只是将 $1 解释为字符串并且没有给出结果。

提前致谢,

4

1 回答 1

1

AE'$1'是一个字符串文字(使用转义字符串语法),包含一个美元符号,后跟一个。未加引号$1是函数的第一个参数。所以这:

regexp_matches(t, E'($1[\+])([0-9]+)'))[2]::integer

如您所见,不会$1用函数的第一个参数插入 。

正则表达式只是一个字符串,一个具有内部结构但仍然只是一个字符串的字符串。如果您知道这$1将是一个正常的词,那么您可以说:

regexp_matches(t, E'(' || $1 || E'[\+])([0-9]+)'))[2]::integer

将您的字符串粘贴到合适的正则表达式中。然而,最好是有点偏执,迟早有人会用这样的字符串调用你的函数,'ha ha ('所以你应该为此做好准备。我能想到的将任意字符串添加到正则表达式的最简单方法是转义所有非单词字符:

-- Don't forget to escape the escaped escapes! Hence all the backslashes.
str := regexp_replace($1, E'(\\W)', E'\\\\\\1', 'g');

然后粘贴str到上面的正则表达式中:

regexp_matches(t, E'(' || str || E'[\+])([0-9]+)'))[2]::integer

或者更好的是,在外部构建正则表达式regexp_matches以减少嵌套括号:

re := E'(' || str || E'[\+])([0-9]+)';
-- ...
select regexp_matches(t, re)[2]::integer ...

PostgreSQL 没有Perl\Q...\E并且元(?q)语法适用于正则表达式的结尾,所以我想不出比转义所有内容并让PostgreSQL 把它整理出来。

使用这种技术,我们可以执行以下操作:

=> do $$
    declare
        m text[];
        s text;
        r text;
    begin
        s = E'''{ha)?';
        r = regexp_replace(s, E'(\\W)', E'\\\\\\1', 'g');
        r = '(ha' || r || ')';
        raise notice '%', r;
        select regexp_matches(E'ha''{ha)?', r) into m;
        raise notice '%', m[1];
    end$$;

并得到预期

NOTICE:  ha'{ha)?

输出。但是如果你省略了regexp_replace转义步骤,你只会得到一个

invalid regular expression: parentheses () not balanced

错误。

顺便说一句,我认为您不需要所有的演员表,所以我将其删除。正则表达式和转义足够嘈杂,没有必要在混合中加入一堆冒号。另外,我不知道您standard_conforming_strings的设置是什么或您使用的是哪个版本的 PostgreSQL,所以我E''到处都使用字符串。您还需要将您的过程切换到 PL/pgSQL ( language plpgsql) 以使转义更容易。

于 2012-06-07T17:13:10.140 回答