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 查询或函数以使其工作?

4

2 回答 2

2

访问(众所周知的)复合类型的字段,您需要将标识符括在括号中。如果没有括号,点之前的标识符将被视为每个 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);
于 2013-02-19T21:18:51.473 回答
1

尝试使用:

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

因为您已将 a 和 b 声明为要返回的表的列。

于 2013-02-19T19:56:50.010 回答