5

在 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;

谢谢

4

4 回答 4

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;

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

select * from unnest(v_ids) where ...
于 2018-04-18T15:10:26.653 回答
5

PostgreSQL 中没有这样的语法,也没有类似的功能。

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

当您在单个 SQL 语句中完成所有工作时,一个更好的选择是使用公用表表达式(CTE,或WITH查询)。这并不适合所有情况。

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

假设这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;

这种特殊情况可以进一步简化为一个普通的 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;
于 2013-04-30T00:08:02.297 回答
2

您也可以使用 PostgreSQL 数组 - 它类似于 Oracle 的集合:

postgres=# create table _foo(a int, b int);
CREATE TABLE
postgres=# insert into _foo values(10,20);
INSERT 0 1

postgres=# create or replace function multiply()
returns setof _foo as $$
/*
 * two tricks are here
 * table name can be used as type name
 * table name can be used as fictive column that packs all fields
 */
declare a _foo[] = (select array(select _foo from _foo));
begin
  return query select * from unnest(a) 
           union
           all select * from unnest(a);
end;
$$ language plpgsql;

CREATE FUNCTION
postgres=# select * from multiply();
 a  | b  
----+----
 10 | 20
 10 | 20
(2 rows)

但在你的情况下,克雷格·林格的提议是完美的,应该更可取。

于 2013-04-30T06:46:06.210 回答
0
-- Fetch the next 5 rows in the cursor_01:
FETCH FORWARD 5 FROM cursor_01;

PostgreSQL 10+ 有效。

https://www.postgresql.org/docs/10/sql-fetch.html

于 2020-09-24T21:19:55.993 回答