使用函数执行具有不同数据类型的多个select语句

时间:2015-10-05 13:43:01

标签: postgresql plpgsql postgresql-9.3

如何使用postgresql中的函数执行具有不同数据类型的多个select语句?

CREATE OR REPLACE FUNCTION multiple3()
  RETURNS TABLE(a text, b text, c character varying, d character varying, e character varying, f character varying, g character varying,h character varying) AS
$BODY$
BEGIN

RETURN QUERY select a,b,c from table 1;

RETURN QUERY select e,f,g,h from table 2;

END
$BODY$
  LANGUAGE plpgsql VOLATILE
  COST 100
  ROWS 1000;


-- here a and e are different data types

1 个答案:

答案 0 :(得分:1)

您不能从plpgsql函数返回具有不同数据类型的行,因为一次调用中的所有返回值必须属于同一类型。

如果要返回具有可变列数的行,则应将recordsetof record声明为函数的返回类型。 但是,在这种情况下,您必须在函数调用中指定预期的行结构。

返回一行的函数应该以{{1​​}}作为返回类型。例如:

record

执行查询时,您必须知道函数返回的列数:

create or replace function test_record(number_of_columns int)
returns record language plpgsql as $$
begin
    case number_of_columns
        when 1 then 
            return row('a'::text);
        when 2 then 
            return row('a'::text, 2::integer);
        else 
            return row('a'::text, 2::integer, 5.5::numeric);
    end case;
end $$;

返回多行的函数应该以{{1​​}}作为返回类型:

select * from test_record(1) as (column1 text);

 column1 
---------
 a

select * from test_record(2) as (column1 text, column2 integer);

 column1 | column2 
---------+---------
 a       |       2

select * from test_record(3) as (column1 text, column2 integer, column3 numeric);

 column1 | column2 | column3 
---------+---------+---------
 a       |       2 |     5.5

-- but:

select * from test_record(3) as (column1 text);
ERROR:  returned record type does not match expected record type
DETAIL:  Number of returned columns (3) does not match expected column count (1).
CONTEXT:  PL/pgSQL function test_record(integer) while casting return value to function's return type

了解详情:7.2.1.4. Table Functions

另一种选择是使用setof record值使行适合返回的类型,例如:

create or replace function test_set_of_record(number_of_columns int)
returns setof record language plpgsql as $$
begin
    case number_of_columns
        when 1 then 
            return query select i::text from generate_series(1, 3) i;
        when 2 then 
            return query select i::text, i from generate_series(1, 3) i;
        else 
            return query select i::text, i, i::numeric from generate_series(1, 3) i;
    end case;
end $$;

select * from test_set_of_record(3) as (column1 text, column2 integer, column3 numeric);

 column1 | column2 | column3 
---------+---------+---------
 1       |       1 |       1
 2       |       2 |       2
 3       |       3 |       3
(3 rows)