【问题标题】:Postgres function to turn regexp_matches SETOF result into an ARRAYPostgres 函数将 regexp_matches SETOF 结果转换为 ARRAY
【发布时间】:2021-11-11 14:03:36
【问题描述】:

我是第一次尝试 pgSQL。

提前非常感谢 - Eugen

我喜欢解决的问题

我喜欢从文本中返回一个具有最小长度的单词数组。选择了regexp_matches,它返回SETOF text[](不是数组)。可能有更好的方法,但这是我选择的。

regexp_matches ( string text, pattern text [, flags text ] ) → setof text[]

问题

当尝试使用来自结果集的单个结果(看似数组)时,它们实际上是 text 类型,但包含 Postgres 数组的大括号。

示例

下面的示例在功能上有效,因为我添加了一个解决方法,使用 trim 函数删除大括号。

下面描述的函数的输出

# select lower_words_arr('there is an answer','\w{3,}') AS words;
NOTICE:  match = {there}
NOTICE:  match = {answer}
     words      
----------------
 {there,answer}
(1 row)

我的问题

为什么会出现,那个单独的 regexp_matches 条目匹配并以 "{txt}" 的形式返回数据,但表现为文本类型而不是 ARRAY?

有没有办法不用我的解决方法?

代码

CREATE OR REPLACE FUNCTION lower_words_arr(input_str text, match_expr text) RETURNS text[] AS $$
DECLARE
    words_arr text[];
    one_match text;
BEGIN
    FOR one_match IN SELECT regexp_matches(lower(input_str), match_expr, 'g') 
    AS match 
    LOOP
        RAISE NOTICE 'match = %', one_match;

        -- But if I write:
        --
        -- RAISE NOTICE 'match = %', one_match[0];
        --
        -- fails with:
        ---
        -- ERROR:  cannot subscript type text because it is not an array
        -- CONTEXT:  SQL statement "SELECT one_match[0]"
        -- PL/pgSQL function lower_words_arr(text,text) line 10 at RAISE
        --
        -- even though this the result returned
        ---
        -- NOTICE:  match = {there}
        -- NOTICE:  match = {answewr}

        words_arr := array_append(words_arr,trim(BOTH '{}' FROM one_match));
    END LOOP;

    RETURN words_arr;
END;
$$ LANGUAGE plpgsql;

【问题讨论】:

  • 会不会是 SELECT 这样做了?试试FOR one_match IN regexp_matches(lower(input_str), match_expr, 'g')
  • 非常感谢,非常感谢您的想法,Postgres 在没有 SELECT ERROR: syntax error at or near "regexp_matches" LINE 6: FOR one_match IN regexp_matches(lower(input_str), match_. ..但我想我正在接近这个案子 - 总是很有趣。

标签: postgresql plpgsql


【解决方案1】:

我现在已经解决了没有trim 解决方法的问题。解决方案来自Postgres documentation。在该页面上查找SELECT (regexp_match('foobarbequebaz', 'bar.*que'))[1];。有了这些知识,我将功能更改为

改进的解决方案

CREATE OR REPLACE FUNCTION lower_words_arr(input_str text, match_expr text) RETURNS text[] AS $$
DECLARE
    words_arr text[];
    one_match text;
BEGIN
    FOR one_match IN SELECT(regexp_matches(lower(input_str), match_expr, 'g'))[1] AS match 
    LOOP
        RAISE NOTICE 'match = %', one_match;
        words_arr := array_append(words_arr,one_match);
    END LOOP;

    RETURN words_arr;
END;
$$ LANGUAGE plpgsql STABLE;

输出

select lower_words_arr('there is an answer - you will find it in the Postgres documentation.','\w{4,}') AS words;
NOTICE:  match = there
NOTICE:  match = answer
NOTICE:  match = will
NOTICE:  match = find
NOTICE:  match = postgres
NOTICE:  match = documentation
                      words                      
-------------------------------------------------
 {there,answer,will,find,postgres,documentation}
(1 row)

结论

我最初的问题已经解决了,但是仍然缺少一个令人费解的理解(不是我最初问题的主题):

  • 为什么从 SELECT 中删除 [1] 时,one_match 变量的行为不像数组?

也许我应该针对该行为提出一个特定的问题...

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-13
    • 1970-01-01
    • 1970-01-01
    • 2020-03-07
    • 2023-01-29
    • 2015-01-09
    相关资源
    最近更新 更多