从函数返回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
通过一个命令返回多行。 -
使用
VALUES
expression式手动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;