PostgreSQL相当于Oracle"批量收集"

Lea*_*dro 0 postgresql plpgsql

在PostgreSQL中存在一些使用批量收集的声明的方法,就像在Oracle中一样?

Oracle中的示例:

create or replace procedure prc_tst_bulk_test is

type typ_person is table of tb_person%rowtype;
v_tb_person typ_person;

begin

select *
bulk collect into v_tb_person
from tb_person;

-- make a selection in v_tb_person, for instance    
select name, count(*) from v_tb_person where age > 50
union 
select name, count(*) from v_tb_person where gender = 1

end;
Run Code Online (Sandbox Code Playgroud)

谢谢

Top*_*ley 9

在 PostgreSQL 10 中,您可以使用array_agg

declare
    v_ids int[];   
begin
    select array_agg(id) INTO v_ids
      from mytable1
     where host = p_host;

    --use v_ids...

end;
Run Code Online (Sandbox Code Playgroud)

您将拥有数组,它可用于使用unnest从中进行选择:

select * from unnest(v_ids) where ...
Run Code Online (Sandbox Code Playgroud)


Cra*_*ger 5

PostgreSQL中没有这样的语法,也没有一个近似的功能等价物.

您可以在PL/PgSQL代码中创建临时表,并将其用于所需目的.PL/PgSQL中的临时表有点烦人,因为名称在会话中是全局的,但它们在PostgreSQL 8.4及更高版本中正常工作.

当您在单个SQL语句中执行所有工作时,更好的替代方法是使用公用表表达式(CTE或WITH查询).这不适合所有情况.

上面的例子可以通过简单RETURN QUERY的PL/PgSQL 更好地解决,但我认为你的真实例子更复杂.

假设这tb_person是一种昂贵的生成视图,您不仅想要在联合的每个分支中进行扫描,您可以执行以下操作:

CREATE OR REPLACE FUNCTION prc_tst_bulk()
RETURNS TABLE (name text, rowcount integer) AS 
$$
BEGIN
    RETURN QUERY
    WITH v_tb_person AS (SELECT * FROM tb_person)
    select name, count(*) from v_tb_person where age > 50
    union 
    select name, count(*) from v_tb_person where gender = 1;
END;
$$ LANGUAGE plpgsql;
Run Code Online (Sandbox Code Playgroud)

这种特殊情况可以进一步简化为一个简单的SQL函数:

CREATE OR REPLACE FUNCTION prc_tst_bulk()
RETURNS TABLE (name text, rowcount integer) AS 
$$
    WITH v_tb_person AS (SELECT * FROM tb_person)
    select name, count(*) from v_tb_person where age > 50
    union 
    select name, count(*) from v_tb_person where gender = 1;
$$ LANGUAGE sql;
Run Code Online (Sandbox Code Playgroud)