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)
谢谢
在 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)
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)