PostgreSQL函数或输出多列的存储过程?

时间:2011-03-28 17:49:31

标签: postgresql stored-procedures plpgsql sql-function

这是我理想的想法。想象一下,我有一个表 A

我想这样做:

SELECT A, func(A) FROM table

并且输出要说4列。

有没有办法做到这一点?我已经看到自定义类型上的东西或任何可以让你获得看起来像

的结果的东西
  

A,(B,C,d)

但是如果我能让一个函数返回多列而不再进行任何重复,那将会非常棒。

有什么能做到这样的事吗?

4 个答案:

答案 0 :(得分:17)

如果函数 func 仅返回包含3个值的1行,例如:

CREATE OR REPLACE FUNCTION func
(
    input_val       integer,
    OUT output_val1 integer,
    OUT output_val2 integer,
    OUT output_val3 integer
)
AS $$
BEGIN
  output_val1 := input_val + 1;
  output_val2 := input_val + 2;
  output_val3 := input_val + 3;
END;
$$ LANGUAGE plpgsql;

然后执行SELECT a, func(a) FROM table1您将获得:

a       | func
integer | record
========|==========
1       | (2, 3, 4)
2       | (3, 4, 5)
3       | (4, 5, 6)

但是,如果你执行:

SELECT a, (f).output_val1, (f).output_val2, (f).output_val3
FROM (SELECT a, func(a) AS f FROM table1) AS x

你会得到:

a       | output_val1 | output_val2 | output_val3
integer | integer     | integer     | integer
========|=============|=============|=============
1       | 2           | 3           | 4
2       | 3           | 4           | 5
3       | 4           | 5           | 6

或者,使用CTE(公用表格式),如果执行:

WITH temp AS (SELECT a, func(a) AS f FROM table1)
SELECT a, (f).output_val1, (f).output_val2, (f).output_val3 FROM temp

你也会得到:

a       | output_val1 | output_val2 | output_val3
integer | integer     | integer     | integer
========|=============|=============|=============
1       | 2           | 3           | 4
2       | 3           | 4           | 5
3       | 4           | 5           | 6

注意:您也可以使用以下查询来获得相同的结果:

SELECT a, (f).*
FROM (SELECT a, func(a) AS f FROM table1) AS x

WITH temp AS (SELECT a, func(a) AS f FROM table1)
SELECT a, (f).* FROM temp

答案 1 :(得分:6)

我同意bambam的回答,但是我想指出JackPDouglas的更简洁的语法SELECT a, (func(a)).* FROM table1,从我的测试中,实际上会为每个返回的列执行一次函数,而CTE表达式只执行一次函数。因此,如果函数需要很长时间才能执行,则首选CTE表达式。

答案 2 :(得分:2)

如果函数总是返回3列,你可以这样做:

CREATE TYPE sometype AS (b INT, c TEXT, d TEXT);

CREATE OR REPLACE FUNCTION func(a TEXT) RETURNS SETOF sometype AS $$
BEGIN
  RETURN QUERY EXECUTE 'SELECT b, c, d FROM ' || a;
END;
$$ LANGUAGE plpgsql;

SELECT a, (f).b, (f).c, (f).d 
FROM (SELECT a, func(a) AS f FROM table) x;

如果您可以在视图中访问该表,也许您可​​以以某种方式创建视图

CREATE VIEW v AS 
SELECT 'tab1' AS a, b, c, d FROM tab1 WHERE 'tab1' IN (SELECT a FROM table)
UNION
SELECT 'tab2' AS a, b, c, d FROM tab2 WHERE 'tab2' IN (SELECT a FROM table)
UNION
SELECT 'tab3' AS a, b, c, d FROM tab3 WHERE 'tab3' IN (SELECT a FROM table);

然后它只是一个SELECT * FROM v。但是,这似乎可以使用Inheritance

答案 3 :(得分:0)

我想你会想要返回一个包含多列的记录吗?在这种情况下,您可以使用返回类型RECORD。这将允许您返回包含任意数量列的匿名变量。您可以在此处找到有关所有不同变量的更多信息:

http://www.postgresql.org/docs/9.0/static/plpgsql-declarations.html

关于退货类型:

http://www.postgresql.org/docs/9.0/static/xfunc-sql.html#XFUNC-OUTPUT-PARAMETERS

如果要返回包含多列的多个记录,请首先检查并查看是否必须使用存储过程。可以选择仅使用VIEW(并使用WHERE子句查询)。如果这不是一个好的选择,则有可能从版本9.0中的存储过程返回TABLE