从函数返回setoflogging(虚拟表)

我需要一个Postgres函数来返回一个虚拟表(如在Oracle中)与自定义内容。 该表将有3列和未知数量的行。

我只是无法在互联网上find正确的语法。

想象一下:

CREATE OR REPLACE FUNCTION "public"."storeopeninghours_tostring" (numeric) RETURNS setof record AS DECLARE open_id ALIAS FOR $1; returnrecords setof record; BEGIN insert into returnrecords('1', '2', '3'); insert into returnrecords('3', '4', '5'); insert into returnrecords('3', '4', '5'); RETURN returnrecords; END; 

这是怎么写的?

(这全部用postgresql 8.3.7进行testing – 你有一个更早的版本吗?只是看看你使用“ALIAS FOR $ 1”)

 CREATE OR REPLACE FUNCTION storeopeninghours_tostring(numeric) RETURNS SETOF RECORD AS $$ DECLARE open_id ALIAS FOR $1; result RECORD; BEGIN RETURN QUERY SELECT '1', '2', '3'; RETURN QUERY SELECT '3', '4', '5'; RETURN QUERY SELECT '3', '4', '5'; END $$; 

如果您有要返回的logging或行variables(而不是查询结果),请使用“RETURN NEXT”而不是“RETURN QUERY”。

要调用该函数,您需要执行如下操作:

 select * from storeopeninghours_tostring(1) f(a text, b text, c text); 

所以你必须定义你希望函数的输出行模式在查询中。 为了避免这种情况,您可以在函数定义中指定输出variables:

 CREATE OR REPLACE FUNCTION storeopeninghours_tostring(open_id numeric, a OUT text, b OUT text, c OUT text) RETURNS SETOF RECORD LANGUAGE 'plpgsql' STABLE STRICT AS $$ BEGIN RETURN QUERY SELECT '1'::text, '2'::text, '3'::text; RETURN QUERY SELECT '3'::text, '4'::text, '5'::text; RETURN QUERY SELECT '3'::text, '4'::text, '5'::text; END $$; 

(不太清楚为什么额外的::文本转换是必需的…'1'是默认的varchar?)

目前所有的答案已经过时,或者效率低下。

假设你想返回三个integer列。

PL / pgSQLfunction

下面是你如何使用现代的PL / pgSQL(PostgreSQL 8.4或更高版本):

 CREATE OR REPLACE FUNCTION f_foo(open_id numeric) RETURNS TABLE (a int, b int, c int) AS $func$ BEGIN -- do something with open_id? RETURN QUERY VALUES (1,2,3) , (3,4,5) , (3,4,5); END $func$ LANGUAGE plpgsql IMMUTABLE ROWS 3; 

呼叫:

 SELECT * FROM f_foo(1); 

重点

  • 使用RETURNS TABLE来定义要返回的ad-hoc行types。
    或者RETURNS SETOF mytbl以使用预定义的行types。

  • 使用RETURN QUERY通过一个命令返回多行。

  • 使用VALUESexpression式手动input多行。 这是标准的SQL,并且一直存在。

  • 使用参数名称(open_id numeric)而不是ALIAS ,这对于标准参数名称是不鼓励的。 在这个例子中,参数不被使用,只是噪音…

  • 不需要双引号完美的合法标识符。 双引号只需要强制以其他方式非法的名称(混合大小写,非法字符或保留字)。

  • function波动可能是IMMUTABLE ,因为结果不会改变。

  • ROWS 3是可选的,但是由于我们知道有多less行被返回,我们不妨将它声明为Postgres。 可以帮助查询计划者select最佳计划。

简单的SQL

对于这样的简单情况,您可以使用普通的SQL语句:

 VALUES (1,2,3), (3,4,5), (3,4,5) 

或者,如果您想(或必须)定义特定的列名称和types:

 SELECT * FROM ( VALUES (1::int, 2::int, 3::int) , (3, 4, 5) , (3, 4, 5) ) AS t(a, b, c); 

SQL函数

你可以把它包装成一个简单的SQL函数 。 没有函数参数的例子,因为它没有被使用:

 CREATE OR REPLACE FUNCTION f_foo() RETURNS TABLE (a int, b int, c int) AS $func$ VALUES (1, 2, 3) , (3, 4, 5) , (3, 4, 5); $func$ LANGUAGE sql IMMUTABLE ROWS 3; 

我在function上使用临时表。 您需要在数据库上创build一个返回types,然后创build该types的variables以返回。 下面是一些示例代码。

 CREATE TYPE storeopeninghours_tostring_rs AS (colone text, coltwo text, colthree text ); CREATE OR REPLACE FUNCTION "public"."storeopeninghours_tostring" () RETURNS setof storeopeninghours_tostring_rs AS $BODY$ DECLARE returnrec storeopeninghours_tostring_rs; BEGIN BEGIN CREATE TEMPORARY TABLE tmpopeninghours ( colone text, coltwo text, colthree text ); EXCEPTION WHEN OTHERS THEN TRUNCATE TABLE tmpopeninghours; -- TRUNCATE if the table already exists within the session. END; insert into tmpopeninghours VALUES ('1', '2', '3'); insert into tmpopeninghours VALUES ('3', '4', '5'); insert into tmpopeninghours VALUES ('3', '4', '5'); FOR returnrec IN SELECT * FROM tmpopeninghours LOOP RETURN NEXT returnrec; END LOOP; END; $BODY$ LANGUAGE 'plpgsql' VOLATILE; select * from storeopeninghours_tostring() 

对于那些在这里寻找MSSQL等同于创build一个临时表和抛出它的logging作为您的返回…在PostgreSQL中不存在:( – 您必须定义返回types。有两种方法可以做这是在函数创build时或创build查询时。

看到这里: http : //wiki.postgresql.org/wiki/Return_more_than_one_row_of_data_from_PL/pgSQL_functions

 CREATE OR REPLACE FUNCTION foo(open_id numeric, OUT p1 varchar, OUT p2 varchar, OUT p3 varchar) RETURNS SETOF RECORD AS $$ BEGIN p1 := '1'; p2 := '2'; p3 := '3'; RETURN NEXT; p1 := '3'; p2 := '4'; p3 := '5'; RETURN NEXT; p1 := '3'; p2 := '4'; p3 := '5'; RETURN NEXT; RETURN; END; $$ LANGUAGE plpgsql;