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

今まで私はこの関数(以下を参照)を作成しましたが、これは非常にうまく機能しますが、パラメーター置換の問題に直面しています...($1の代わりに'data2'を使用できないことがわかります...しかし、$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

Aは、ドル記号の後に 1 が続くE'$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 に答える