【问题标题】:Apply function to every element of an array in a SELECT statement在 SELECT 语句中将函数应用于数组的每个元素
【发布时间】:2013-12-11 23:30:25
【问题描述】:

我列出了 PostgreSQL 模式的所有函数,并且函数的每个参数都需要人类可读的类型。在proallargtypes 中表示为数组的类型 a 的 OID。我可以取消嵌套数组并将format_type() 应用于它,这会导致查询拆分为单个函数的多行。为避免这种情况,我必须再次创建一个外部 SELECTGROUP argtypes,因为显然不能对未嵌套的数组进行分组。所有列都依赖于 proname 但我必须在 GROUP BY 子句中列出所有列,这是不必要的,但 proname is not a primary key

有没有更好的方法来实现我这样的输出目标:

proname | ...   | protypes
-------------------------------------
test    | ...   | {integer,integer}

我目前正在使用这个查询:

SELECT
          proname,
          prosrc,
          pronargs,
          proargmodes,
          array_agg(proargtypes), -- see here
          proallargtypes,
          proargnames,
          prodefaults,
          prorettype,
          lanname
FROM (
        SELECT
          p.proname,
          p.prosrc,
          p.pronargs,
          p.proargmodes,
          format_type(unnest(p.proallargtypes), NULL) AS proargtypes, -- and here
          p.proallargtypes,
          p.proargnames,
          pg_get_expr(p.proargdefaults, 0) AS prodefaults,
          format_type(p.prorettype, NULL) AS prorettype,
          l.lanname
        FROM pg_catalog.pg_proc p
        JOIN pg_catalog.pg_language l
        ON l.oid = p.prolang
        JOIN pg_catalog.pg_namespace n
        ON n.oid = p.pronamespace
        WHERE n.nspname = 'public'
) x
GROUP BY proname, prosrc, pronargs, proargmodes, proallargtypes, proargnames, prodefaults, prorettype, lanname

【问题讨论】:

    标签: arrays postgresql select


    【解决方案1】:

    您可以使用内部“未记录”函数 pg_catalog.pg_get_function_arguments(p.oid)。

    postgres=# SELECT pg_catalog.pg_get_function_arguments('fufu'::regproc);
     pg_get_function_arguments 
    ---------------------------
     a integer, b integer
    (1 row)
    

    现在,没有构建“地图”功能。如此混乱,array_agg 只是一种可能。您可以使用自己的自定义函数来简化生活:

    CREATE OR REPLACE FUNCTION format_types(oid[])
    RETURNS text[] AS $$
       SELECT ARRAY(SELECT format_type(unnest($1), null))
    $$ LANGUAGE sql IMMUTABLE;
    

    结果

    postgres=# SELECT format_types('{21,22,23}');
              format_types          
    -------------------------------
    {smallint,int2vector,integer}
    (1 row)
    

    那么你的查询应该是:

    SELECT proname, format_types(proallargtypes)
       FROM pg_proc
      WHERE pronamespace = 2200 AND proallargtypes;
    

    但结果可能不会是预期的,因为只有在使用 OUT 参数时,proallargtypes 字段才不是空的。它通常是空的。您应该查看 proargtypes 字段,但它是 oidvector 类型 - 所以您应该先转换为 oid[]。

    postgres=# SELECT proname, format_types(string_to_array(proargtypes::text,' ')::oid[])
                  FROM pg_proc
                 WHERE pronamespace = 2200
                 LIMIT 10;
               proname            |                    format_types                    
    ------------------------------+----------------------------------------------------
     quantile_append_double       | {internal,"double precision","double precision"}
     quantile_append_double_array | {internal,"double precision","double precision[]"}
     quantile_double              | {internal}
     quantile_double_array        | {internal}
     quantile                     | {"double precision","double precision"}
     quantile                     | {"double precision","double precision[]"}
     quantile_cont_double         | {internal}
     quantile_cont_double_array   | {internal}
     quantile_cont                | {"double precision","double precision"}
     quantile_cont                | {"double precision","double precision[]"}
    (10 rows)
    

    【讨论】:

    • 谢谢!我将对此进行测试并返回给您。可悲的是,我无法创建自己的函数,因为我正在编写一个独立于数据库的工具,它可以列出函数。只是读取权限。
    • 太棒了,我知道 OUT 参数的问题。我需要解决我的问题是您的自定义函数的 ARRAY() 函数。非常感谢!
    • @AmShaegar:请注意 - ARRAY() 不是函数 - 它是“带有子选择的数组构造函数”。语法相同,但语义有点不同:)
    猜你喜欢
    • 1970-01-01
    • 2022-01-21
    • 1970-01-01
    • 2015-09-09
    • 2021-05-25
    • 2016-08-19
    • 2013-10-13
    • 2021-05-02
    • 2012-01-24
    相关资源
    最近更新 更多