2012-08-30 42 views
2

有一個返回3個參數,其中一個是複合類型的函數:

CREATE OR REPLACE FUNCTION f1(
    p_text text, 
    OUT result_status_id smallint, 
    OUT result_status_msg text, 
    OUT result_my_type my_type 
) 
    RETURNS record AS 
$BODY$ 
--body here 
$BODY$ 
LANGUAGE 'plpgsql' VOLATILE SECURITY DEFINER 
    COST 100 

的複合型my_type看起來像以下:

CREATE TYPE my_type AS 
    (d_real real, 
    d_int1 integer, 
    d_int2 integer, 
    d_int3 integer, 
    d_int4 integer, 
    d_int5 integer, 
    d_int6 integer, 
    d_int7 integer, 
    d_int8 integer, 
    d_int9 integer, 
    d_int10 integer, 
    d_bool boolean, 
    d_date date, 
    d_text text 
); 

還有另外一個函數F2,在它的身上調用函數F1:

CREATE OR REPLACE FUNCTION f2(
    p_text text 
) 
    RETURNS record AS 
$BODY$ 
DECLARE 
    l_status_id smallint; 
    l_status_msg text; 
    l_my_type my_type; 
BEGIN 
--some logic here 

--this statement fails 
    SELECT * FROM f1(p_text) 'x' 
    INTO l_status_id, l_status_msg, l_my_type; 

--logic continues here 
END; 
$BODY$ 
    LANGUAGE 'plpgsql' VOLATILE SECURITY DEFINER 
    COST 100; 

的問題是,當高管使用函數sql我收到以下錯誤:

ERROR: "l_my_type" is not a scalar variable 

如何可能從另一個函數獲取複合類型的對象?

回答

2

你違反了規則。 The manual:

where target can be a record variable, a row variable, or a comma-separated list of simple variables and record/row fields.

一個記錄或者行變量不能是多個項目INTO列表的一部分。解決此
方式一:

CREATE OR REPLACE FUNCTION f2(p_text text) 
    RETURNS record AS 
$BODY$ 
DECLARE 
    r   record; 
    l_status_id smallint; 
    l_status_msg text; 
    l_my_type my_type; 
BEGIN 
    SELECT * 
    FROM f1(p_text) x -- don't single quote 'x' 
    INTO r; 

    l_status_id := r.result_status_id; 
    l_status_msg := r.result_status_msg; 
    l_my_type := r.result_my_type; 

    RETURN r; -- or whatever .. 
END; 
$BODY$ 
    LANGUAGE plpgsql VOLATILE; 

有更多的方法。這取決於你要去哪裏。我幾乎沒有回到匿名記錄。

+0

這也沒關係,它在x附近沒有單引號。沒有別名功能也是 – Tim

+0

重要的部分是你遇到的錯誤的解釋(對你*和*普通大衆)。如前所述,它有多種方式。在你已經發布簡單任務後,我選擇了一個不同的例子。 –

0

在你F2()函數,你可以做的選擇到一個記錄變量,然後提取你從它需要的東西,如:

CREATE OR REPLACE FUNCTION f2(p_text text) 
    RETURNS record AS 
$BODY$ 
DECLARE 
    record_var record; 
BEGIN 
--this statement was failing 
    SELECT * FROM f1(p_text) INTO record_var; 

SELECT l_my_type.result_my_type.d_int1; -- this should work 

END; 
$BODY$ 
    LANGUAGE 'plpgsql' VOLATILE SECURITY DEFINER 
    COST 100;  
+0

不幸的是,這並沒有爲我工作 – Tim

1

複合類型的元組的那些東西其中之一是支持部分和你遇到奇怪的問題(特別是像存儲這樣的瘦,但這是另一個故事)。你能做到這一點的方法之一是:

CREATE TYPE return_type_for_function AS (
     result_status_id smallint, 
     result_status_msg text, 
     result_my_type my_type 
); 

CREATE FUNCTION myfunc(....) RETURNS return_type_for_function .... 

這是我一直做它的方式。這比使用OUT變量更成熟一些。

這裏有一個簡單的例子:

or_examples=# create table rel_examples.tabletest (id int); 
CREATE TABLE 

or_examples=# create table comp_table_test (test rel_examples.tabletest); 
CREATE TABLE 

or_examples=# create function test(int) returns comp_table_test 
immutable language sql as $$ 
select row(row($1))::comp_table_test; $$; 
CREATE FUNCTION 
or_examples=# select test(1); 
    test 
--------- 
("(1)") 
(1 row) 
+0

+1爲一個可接受的解決方案,但我找到了你可以在我的答案找到的技巧 – Tim

1

然而,@克里斯特拉弗斯提出可接受的解決方案,在我的情況下,它是不幸的是沒有可能引入新的類型,從f1函數返回的數據。

儘管如此,人們可以使用以下語法調用函數f1()的函數f2(),仍然可以得到數據:

CREATE OR REPLACE FUNCTION f2(
    p_text text 
) 
    RETURNS record AS 
$BODY$ 
DECLARE 
    l_status_id smallint; 
    l_status_msg text; 
    l_my_type my_type; 
    l_record record; 
BEGIN 
--some logic here 

--this statement is okay now 
    l_record = f1(p_text); 
    l_status_id = l_record.result_status_id; 
    l_status_msg = l_record.result_status_msg; 
    l_my_type = l_record.result_my_type; 

--logic continues here 
END; 
$BODY$ 
    LANGUAGE 'plpgsql' VOLATILE SECURITY DEFINER 
    COST 100; 
+0

這是更簡單的形式,是的。在另一個註釋中:plpgsql中的賦值運算符是':='。爲了達到目的,'='運算符沒有記錄。考慮這個[相關問題](http://stackoverflow.com/q/7462322/939860)。 –