postgresql 如何从 PL/pgSQL 函数返回多行?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/17244256/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-11 00:14:17  来源:igfitidea点击:

How to return multiple rows from PL/pgSQL function?

postgresqlplpgsql

提问by Asma Zubair

I have spent good amount of time trying to figure it out and I haven't been able to resolve it. So, I need your help please.

我花了很多时间试图弄清楚它,但我一直无法解决它。所以,我需要你的帮助。

I am trying to write a PL/pgSQL function that returns multiple rows. The function I wrote is shown below. But it is not working.

我正在尝试编写一个返回多行的 PL/pgSQL 函数。我写的函数如下所示。但它不起作用。

CREATE OR REPLACE FUNCTION get_object_fields()
RETURNS SETOF RECORD
AS 
$$
DECLARE result_record keyMetrics;
BEGIN
    return QUERY SELECT department_id into result_record.visits 
    from fact_department_daily 
    where report_date='2013-06-07';
    --return result_record;
END

$$ LANGUAGE plpgsql; 

SELECT * FROM get_object_fields;

It is returning this error:

它正在返回此错误:

ERROR: RETURN cannot have a parameter in function returning set;
use RETURN NEXT at or near "QUERY"

错误:RETURN 在函数返回集合中不能有参数;
在“QUERY”处或附近使用 RETURN NEXT

采纳答案by Pavel Stehule

I see more bugs:

我看到更多错误:

first, a SET RETURNING FUNCTIONS call has following syntax

首先,SET RETURNING FUNCTIONS 调用具有以下语法

SELECT * FROM get_object_fields()

second - RETURN QUERY forwards query result to output directly. You cannot store this result to variable - it is not possible ever in PostgreSQL now.

第二 - RETURN QUERY 将查询结果直接转发到输出。您不能将此结果存储到变量中 - 现在在 PostgreSQL 中是不可能的。

BEGIN
  RETURN QUERY SELECT ....; -- result is forwarded to output directly
  RETURN;   -- there will not be any next result, finish execution
END;

third - these simple functions is better to implement in SQL languages

第三 - 这些简单的功能最好用 SQL 语言实现

CREATE OR REPLACE FUNCTION get_object_fields()
RETURNS SETOF RECORD AS $$
SELECT department_id WHERE ...
$$ LANGUAGE sql STABLE;

回答by Erwin Brandstetter

After fixing the bugs @Pavel already pointed out, also define your return typeproperly, or you have to provide a column definition list with every call.

在修复@Pavel 已经指出的错误之后,还要正确定义您的返回类型,或者您必须在每次调用时提供一个列定义列表。

This call:

这个电话:

SELECT * FROM get_object_fields()

demands that Postgres knows how to expand *. Since you are returning anonymous records, you'd get an exception:

要求 Postgres 知道如何扩展*。由于您要返回匿名记录,您会得到一个例外:

ERROR: a column definition list is required for functions returning "record"

错误:返回“记录”的函数需要列定义列表

Oneway (of several) to fix this is with RETURNS TABLE(Postgres 8.4+):

解决此问题的一种方法(几种)是使用RETURNS TABLE(Postgres 8.4+):

CREATE OR REPLACE FUNCTION get_object_fields()
  RETURNS TABLE (department_id int) AS 
$func$
BEGIN
   RETURN QUERY
   SELECT department_id
   FROM   fact_department_daily 
   WHERE  report_date = '2013-06-07';
END
$func$ LANGUAGE plpgsql;

Works for SQL functions just the same.

对 SQL 函数同样适用。

More details and links in this closely related answer:
PostgreSQL: ERROR: 42601: a column definition list is required for functions returning "record"

此密切相关的答案中的更多详细信息和链接:
PostgreSQL:错误:42601:返回“记录”的函数需要列定义列表

回答by superlogical

Here's one way

这是一种方法

drop function if exists get_test_type();

drop type if exists test_comp;
drop type if exists test_type;
drop type if exists test_person;

create type test_type as (
  foo int, 
  bar int
);

create type test_person as (
  first_name text, 
  last_name text
);

create type test_comp as 
(
  prop_a test_type[], 
  prop_b test_person[]
);


create or replace function get_test_type()
returns test_comp
as $$
declare
  a test_type[];
  b test_person[];
  x test_comp;
begin

  a := array(
    select row (m.message_id, m.message_id) 
    from message m
  );

  -- alternative 'strongly typed'
  b := array[
    row('Bob', 'Jones')::test_person,
    row('Mike', 'Reid')::test_person
  ]::test_person[];

  -- alternative 'loosely typed'
  b := array[
    row('Bob', 'Jones'),
    row('Mike', 'Reid')
  ];

  -- using a select
  b := array (
    select row ('Jake', 'Scott')
    union all 
    select row ('Suraksha', 'Setty')
  );  

  x := row(a, b);

  return x;  
end;
$$
language 'plpgsql' stable;


select * from get_test_type();