2012-12-10 59 views
4

我正在学习如何在Postgresql中编写函数。我已经定义了一个名为_tmp_myfunction()这需要在id并返回一个表函数(我也定义一个名为_tmp_mytable表对象类型)在Postgresql中创建一个不返回复合值的函数

-- create object type to be returned 
CREATE TYPE _tmp_mytable AS (
    id  integer, 
    cost double precision 
    ); 

-- create function which returns query 
CREATE OR REPLACE FUNCTION _tmp_myfunction(
    id integer 
    ) 
RETURNS SETOF _tmp_mytable AS $$ 
BEGIN 
    RETURN QUERY 
    SELECT 
    sales.gid, 
    cost 
    FROM 
    sales 
    WHERE 
    id = sales.gid; 
    END; 
$$ LANGUAGE plpgsql; 

,当我用一个id并使用以下方法调用它也能正常工作:

SELECT * FROM _tmp_myfunction(402); 

enter image description here

我想做什么就能做的是调用它,而是利用价值,而不只是一个值的列。但是,如果我用下面的办法我结束了在一个列的表的所有值,以逗号分隔:

-- call function using all values in a column 
SELECT _tmp_myfunction(t.id) 
FROM transactions as t; 

enter image description here

我明白,我可以得到相同的结果,如果我用SELECT _tmp_myfunction(402);而不是SELECT * FROM _tmp_myfunction(402);,但我不知道如何构建函数,以便在传入值列时不会获得合成值。

+0

刚刚更新了我的变量名称,使其更清晰一些(我改变了它们使我的问题更清晰,并错过了会有冲突)。 – djq

+1

@ErwinBrandstetter虽然你可以在'SELECT'中调用一个返回函数,但这种行为真的很奇怪。这是一个传统的PostgreSQL特定的黑客,只要PostgreSQL 9.3的'LATERAL'可用就应该立即放弃。如果奇怪,比较'SELECT generate_series(1,3),generate_series(1,3);'到'SELECT generate_series(1,3),generate_series(1,4);'。第一个按顺序返回三行,结果对。第二个返回*十二*行,所有可能的结果配对,就像一个叉积。 –

回答

2

你可以写这样的事情:

SELECT (t2.function_row).id, 
     (t2.function_row).cost 
FROM (SELECT _tmp_myfunction(t.id) as function_row 
    FROM transactions t) t2; 

它会给你的领域,而不是复合行。

+1

请注意,PostgreSQL可能会为每行重复执行一次该函数,每个函数(func_row).column一次。在函数中添加一个'RAISE NOTICE'来查看我的意思。 9.3的'LATERAL'支持应该最终解决这个问题。有一篇详细和实例的相关文章,我目前似乎无法找到它。 –

+0

@克雷格:[你可能是指这个。](http://www.depesz.com/2012/08/19/waiting-for-9-3-implement-sql-standard-lateral-subqueries/)展望未来该功能也是如此。 –

相关问题