2013-02-19 67 views
3

兩個值這個函數的函數:插入使用返回每

CREATE OR REPLACE FUNCTION fn_test1() 
    RETURNS SETOF date AS 
$BODY$ 
declare 
i int; 
begin 

i:=0; 
while i<5 loop 
    return next '2001-01-02'::date; 
    i:=i+1; 
end loop; 


end 
$BODY$ 
    LANGUAGE plpgsql VOLATILE 
    COST 100 
    ROWS 1000; 

下表:

CREATE TABLE teste1 
(
    teste1_id serial NOT NULL, 
    num integer, 
    fn_date date) 

像這樣的INSERT工作得很好(插入5行):

Insert into teste1(num,fn_date) 
select 1, fn_test1(); 

但是,如果我想有一個函數返回兩個日期在一行中,並且一個有2列日期的表格,我應該怎麼做?我到目前爲止做出這樣的:

CREATE OR REPLACE FUNCTION fn_test2() 
    RETURNS TABLE(a date, b date) AS 
$BODY$ 
declare 
_start_date date; 
_end_date date; 
begin 

_start_date:='2001-01-01'::date; 
_end_date:='2002-01-01'::date; 

i:=0; 
while i < 5 loop 
    return query(select _start_date,_end_date); 
    i:=i+1; 
end loop; 
end 
$BODY$ 
    LANGUAGE plpgsql VOLATILE 
    COST 100 
    ROWS 1000; 

而這個表:

CREATE TABLE teste2 
(
    teste2_id serial NOT NULL, 
    num integer, 
    start_date date, 
    end_date date) 

現在,我不能做到這一點:

INSERT INTO teste2(num,start_date,end_date) 
SELECT 1, fn_test2(); 

我所做的函數返回setof mytype (創建一個有兩個日期的類型),但它似乎也做同樣的事情。 我該如何修改INSERT查詢或函數來使其工作?

回答

1

嘗試使用:

INSERT INTO teste2(num,start_date,end_date) 
SELECT 1, f.a, f.b FROM fn_test2() AS f; 

,因爲你已經聲明A和B爲被返回的表列。

2

若要access fields of a (well known) composite type,您需要將標識符包裝在括號中。如果沒有括號,點之前的標識符將被視爲每個SQL語法規則的表名稱。這會工作:

SELECT 1, (fn_test2()).* 

順便說一句,你的虛函數可以是簡單的:

CREATE OR REPLACE FUNCTION fn_test2() 
    RETURNS TABLE(a date, b date) AS 
$func$ 
BEGIN 

a := '2001-01-01'::date; 
b := '2002-01-01'::date; 

FOR i in 0 .. 4 LOOP 
    RETURN NEXT; 
END LOOP; 

END 
$func$ LANGUAGE plpgsql; 

或者使用這個簡單的SQL語句generate_series()達到同樣的效果:

SELECT 1, '2001-01-01'::date AS a, '2002-01-01'::date AS b 
FROM generate_series(0,4); 
+0

我做函數中有一個RAISE NOTICE,看起來函數已經被你調用了兩次。查詢@ sandesh247寫道似乎沒有這個問題。 – NewK 2013-02-20 03:30:01

+0

@NewK:這是目前Postgres版本的一個弱點。 '*'分解爲單獨的列,每個列被分開調用。提供的@ sandesh247這樣的子查詢避免了多次調用。 – 2013-02-20 11:54:49