我需要一个Postgres函数来返回一个带有自定义内容的虚拟表(就像在Oracle中一样)。该表将有3列和未知行数。
我在互联网上找不到正确的语法。
想象一下:
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;
这是如何正确写的?
答案 0 :(得分:37)
(这都是用postgresql 8.3.7测试的 - 你有早期版本吗?只看你使用“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
$$;
如果要返回记录或行变量(而不是查询结果),请使用“RETURN NEXT”而不是“RETURN QUERY”。
要调用此功能,您需要执行以下操作:
select * from storeopeninghours_tostring(1) f(a text, b text, c text);
因此,您必须定义您希望函数的输出行模式在查询中的内容。为避免这种情况,您可以在函数定义中指定输出变量:
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
$$;
(不太确定为什么extra :: text强制转换是必需的...'1'默认情况下是varchar?)
答案 1 :(得分:34)
所有当前存在的答案都已过时或开始时效率低下。
假设您要返回三个integer
列。
以下是使用现代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
定义要返回的临时行类型
或RETURNS SETOF mytbl
使用预定义的行类型。
使用RETURN QUERY
通过一个命令返回多行。
使用VALUES
表达式手动输入多行。这是标准的SQL,并且一直在,。
对标准参数名称使用参数名称(open_id numeric)
而不是ALIAS
, which is discouraged。在示例中,不使用参数,只是噪声......
无需双引号完全合法的标识符。双引号只需要强制使用其他非法名称(混合大小写,非法字符或保留字)。
Function volatility can be IMMUTABLE
,因为结果永远不会改变。
ROWS 3
是可选的,但由于我们知道返回了多少行,我们不妨将其声明为Postgres。可以帮助查询计划员选择最佳计划。
对于这样的简单情况,您可以使用纯SQL语句:
VALUES (1,2,3), (3,4,5), (3,4,5)
或者,如果您希望(或有)定义特定的列名称和类型:
SELECT *
FROM (
VALUES (1::int, 2::int, 3::int)
, (3, 4, 5)
, (3, 4, 5)
) AS t(a, b, c);
您可以将其包装成简单的SQL function。没有函数参数的示例,因为它没有使用:
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;
答案 2 :(得分:23)
我在我的函数中使用了很多临时表。您需要在数据库上创建返回类型,然后创建要返回的该类型的变量。下面是示例代码。
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()
答案 3 :(得分:8)
对于那些已经登陆这里寻找MSSQL相当于创建临时表并将其记录转储为返回的人...在PostgreSQL中不存在:( - 你必须定义返回类型。有两个在创建函数时或在创建查询时执行此操作的方法。
见这里: http://wiki.postgresql.org/wiki/Return_more_than_one_row_of_data_from_PL/pgSQL_functions
答案 4 :(得分:6)
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;