在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;
谢谢
答案 0 :(得分: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;
答案 1 :(得分: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)
但在你的情况下,克雷格林格的建议是完美的,应该更好。
答案 2 :(得分:1)
在PostgreSQL 10中,您可以使用 array_agg :
select * from unnest(v_ids) where ...
您将拥有数组,可以使用不需要来选择它:
var authContext = new AuthenticationContext(config);
var isCallback = authContext.isCallback(window.location.hash);
authContext.handleWindowCallback();
if (isCallback && !authContext.getLoginError()) {
window.location = authContext._getItem(authContext.CONSTANTS.STORAGE.LOGIN_REQUEST);
}
var user = authContext.getCachedUser();
if (!user) {
authContext.login();
}
答案 3 :(得分:0)
-- Fetch the next 5 rows in the cursor_01:
FETCH FORWARD 5 FROM cursor_01;
PostgreSQL 10以上版本有效。