postgresql 是否有办法从存储过程/函数返回(不同表的)结果集

wbrvyc0a  于 2022-12-12  发布在  PostgreSQL
关注(0)|答案(1)|浏览(144)

我想一次从多个表中提取数据。有没有办法从存储过程/函数返回(不同表的)结果集?

gpfsuwkq

gpfsuwkq1#

动态refcursor可用于:

CREATE OR REPLACE FUNCTION public.foo(tabname character varying)
 RETURNS refcursor
 LANGUAGE plpgsql
AS $function$
declare r refcursor;
begin
  open r for execute format('select * from %I', tabname);
  return r;
end;
$function$

(2022-12-09 06:41:42) postgres=# begin;
BEGIN
(2022-12-09 06:42:12) postgres=# select foo('pg_class');
┌────────────────────┐
│        foo         │
╞════════════════════╡
│ <unnamed portal 1> │
└────────────────────┘
(1 row)

(2022-12-09 06:42:35) postgres=# fetch 10 from "<unnamed portal 1>";
┌──────┬─────────────────────┬──────────────┬─────────┬───────────┬──────────┬───────┬─────────────┬───────────────┬──────────┬───────────┬─────
│ oid  │       relname       │ relnamespace │ reltype │ reloftype │ relowner │ relam │ relfilenode │ reltablespace │ relpages │ reltuples │ rela
╞══════╪═════════════════════╪══════════════╪═════════╪═══════════╪══════════╪═══════╪═════════════╪═══════════════╪══════════╪═══════════╪═════
│ 2619 │ pg_statistic        │           11 │   10029 │         0 │       10 │     2 │        2619 │             0 │       19 │       407 │     
│ 1247 │ pg_type             │           11 │      71 │         0 │       10 │     2 │           0 │             0 │       15 │       611 │     
│ 2836 │ pg_toast_1255       │           99 │       0 │         0 │       10 │     2 │           0 │             0 │        1 │         3 │     
│ 2837 │ pg_toast_1255_index │           99 │       0 │         0 │       10 │   403 │           0 │             0 │        1 │         0 │     
│ 4171 │ pg_toast_1247       │           99 │       0 │         0 │       10 │     2 │           0 │             0 │        0 │         0 │     
│ 4172 │ pg_toast_1247_index │           99 │       0 │         0 │       10 │   403 │           0 │             0 │        1 │         0 │     
│ 2830 │ pg_toast_2604       │           99 │       0 │         0 │       10 │     2 │        2830 │             0 │        0 │         0 │     
│ 2831 │ pg_toast_2604_index │           99 │       0 │         0 │       10 │   403 │        2831 │             0 │        1 │         0 │     
│ 2832 │ pg_toast_2606       │           99 │       0 │         0 │       10 │     2 │        2832 │             0 │        0 │         0 │     
│ 2833 │ pg_toast_2606_index │           99 │       0 │         0 │       10 │   403 │        2833 │             0 │        1 │         0 │     
└──────┴─────────────────────┴──────────────┴─────────┴───────────┴──────────┴───────┴─────────────┴───────────────┴──────────┴───────────┴─────
(10 rows)
(2022-12-09 06:43:31) postgres=# close "<unnamed portal 1>";
CLOSE CURSOR
(2022-12-09 06:43:54) postgres=# select foo('pg_proc');
┌────────────────────┐
│        foo         │
╞════════════════════╡
│ <unnamed portal 2> │
└────────────────────┘
(1 row)

(2022-12-09 06:44:03) postgres=# fetch 3 from "<unnamed portal 2>";
┌──────┬─────────┬──────────────┬──────────┬─────────┬─────────┬─────────┬─────────────┬────────────┬─────────┬───────────┬──────────────┬──────
│ oid  │ proname │ pronamespace │ proowner │ prolang │ procost │ prorows │ provariadic │ prosupport │ prokind │ prosecdef │ proleakproof │ prois
╞══════╪═════════╪══════════════╪══════════╪═════════╪═════════╪═════════╪═════════════╪════════════╪═════════╪═══════════╪══════════════╪══════
│ 1242 │ boolin  │           11 │       10 │      12 │       1 │       0 │           0 │ -          │ f       │ f         │ f            │ t    
│ 1243 │ boolout │           11 │       10 │      12 │       1 │       0 │           0 │ -          │ f       │ f         │ f            │ t    
│ 1244 │ byteain │           11 │       10 │      12 │       1 │       0 │           0 │ -          │ f       │ f         │ f            │ t    
└──────┴─────────┴──────────────┴──────────┴─────────┴─────────┴─────────┴─────────────┴────────────┴─────────┴───────────┴──────────────┴──────
(3 rows)
(2022-12-09 06:44:16) postgres=# close "<unnamed portal 2>";
CLOSE CURSOR
(2022-12-09 06:44:21) postgres=# commit;
COMMIT

对于更多游标:

CREATE OR REPLACE FUNCTION public.foo2(tabname1 character varying, tabname2 character varying)
 RETURNS SETOF refcursor
 LANGUAGE plpgsql
AS $function$
declare r refcursor;
begin
  open r for execute format('select * from %I', tabname1);
  return next r;
  r := NULL; -- re initialize refcursor
  open r for execute format('select * from %I', tabname2);
  return next r;
end;
$function$

(2022-12-09 06:58:33) postgres=# begin;
BEGIN
(2022-12-09 06:58:36) postgres=# select * from foo2('pg_class', 'pg_proc');
┌────────────────────┐
│        foo2        │
╞════════════════════╡
│ <unnamed portal 5> │
│ <unnamed portal 6> │
└────────────────────┘
(2 rows)

(2022-12-09 06:58:39) postgres=# fetch 2 from "<unnamed portal 5>";
┌──────┬──────────────┬──────────────┬─────────┬───────────┬──────────┬───────┬─────────────┬───────────────┬──────────┬───────────┬────────────
│ oid  │   relname    │ relnamespace │ reltype │ reloftype │ relowner │ relam │ relfilenode │ reltablespace │ relpages │ reltuples │ relallvisib
╞══════╪══════════════╪══════════════╪═════════╪═══════════╪══════════╪═══════╪═════════════╪═══════════════╪══════════╪═══════════╪════════════
│ 2619 │ pg_statistic │           11 │   10029 │         0 │       10 │     2 │        2619 │             0 │       19 │       407 │            
│ 1247 │ pg_type      │           11 │      71 │         0 │       10 │     2 │           0 │             0 │       15 │       611 │            
└──────┴──────────────┴──────────────┴─────────┴───────────┴──────────┴───────┴─────────────┴───────────────┴──────────┴───────────┴────────────
(2 rows)
(2022-12-09 06:58:47) postgres=# fetch 2 from "<unnamed portal 6>";
┌──────┬─────────┬──────────────┬──────────┬─────────┬─────────┬─────────┬─────────────┬────────────┬─────────┬───────────┬──────────────┬──────
│ oid  │ proname │ pronamespace │ proowner │ prolang │ procost │ prorows │ provariadic │ prosupport │ prokind │ prosecdef │ proleakproof │ prois
╞══════╪═════════╪══════════════╪══════════╪═════════╪═════════╪═════════╪═════════════╪════════════╪═════════╪═══════════╪══════════════╪══════
│ 1242 │ boolin  │           11 │       10 │      12 │       1 │       0 │           0 │ -          │ f       │ f         │ f            │ t    
│ 1243 │ boolout │           11 │       10 │      12 │       1 │       0 │           0 │ -          │ f       │ f         │ f            │ t    
└──────┴─────────┴──────────────┴──────────┴─────────┴─────────┴─────────┴─────────────┴────────────┴─────────┴───────────┴──────────────┴──────
(2 rows)
(2022-12-09 06:58:53) postgres=# commit;
COMMIT

Cursor是一个指向打开的(正在执行的)查询的指针。refcursor值是字符串格式的某个游标的某个句柄。当refcursor变量为NULL时(当它在OPEN语句中使用时),您可以指定自己的名称,或者您的PLpgSQL生成唯一的名称。

相关问题