循环遍历表并返回特定列

时间:2013-11-21 06:52:52

标签: postgresql loops types plpgsql identifier

这是我的功能:

CREATE OR REPLACE FUNCTION getAllFoo()
  RETURNS SETOF "TraderMonthOutstanding" AS
$BODY$
DECLARE
    r  record;
BEGIN
    FOR r IN (select * from "TraderMonthOutstanding"
              where "TraderId"=1 and "IsPaid"=false)
    LOOP

    RETURN NEXT r.TraderId; 

    END LOOP;
    RETURN;
END
$BODY$
LANGUAGE 'plpgsql' ;

我只想从这个循环中TraderId但是我无法得到它,因为它给了我一个错误。
我做错了什么?

3 个答案:

答案 0 :(得分:1)

您声明getAllFoo()RETURNS SETOF "TraderMonthOutstanding"(一组具有表格TraderMonthOutstanding结构的行)但您RETURN NEXT r.TraderId(单个字段)。

您需要将声明的返回类型更改为RETURNS SETOF "TraderMonthOutstanding".TraderId%TYPERETURN NEXT r

答案 1 :(得分:1)

您应该返回setof integersetof TraderMonthOutstanding".TraderId%TYPE

或者更改setof record并返回next r或事件setof TraderMonthOutstanding并将r声明为TraderMonthOutstanding行类型而不是匿名记录。

更好的是,这似乎是一种情况,您应该创建一个视图以避免完全使用函数的开销:

create view getAllFoo as
select *
from "TraderMonthOutstanding"
where "TraderId"=1 and "IsPaid"=false;

select * from getAllFoo;

如果你没有做任何有用的事情,那么在函数中循环遍历这样的集合通常是很糟糕的做法。 (虽然我认为真正的人正在做某事。)

最后,如果你真的想在函数中使用它,请注意你可以return query完全避免循环:

return query
select *
from "TraderMonthOutstanding"
where "TraderId"=1 and "IsPaid"=false;

答案 2 :(得分:1)

@Igor和@Denis说的是什么 如果你实际上需要循环,这在你的例子中并不明显,它会像这样工作:

CREATE OR REPLACE FUNCTION get_all_foo()
  RETURNS SETOF "TraderMonthOutstanding"."TraderId"%TYPE AS
$func$
DECLARE
   r  "TraderMonthOutstanding";  -- use the well known type
BEGIN
   FOR r IN
      SELECT * FROM "TraderMonthOutstanding"
      WHERE  "TraderId" = 1
      AND    "IsPaid" = FALSE    -- no parentheses needed
   LOOP
      -- do whatever necessitates a loop
      RETURN NEXT r."TraderId";
   END LOOP;

   RETURN;
END
$func$ LANGUAGE plpgsql;
  • 不要引用语言名称plpgsql。它是一个标识符,而不是文字。目前的Postgres容忍它,但在未来的版本中可能会被淘汰。

  • 我建议不要在Postgres中使用CaMeL案例标识符 。如果你引用一些,而不是其他人,则更少。这是一个LoaDed Footgun。 Read the manual about identifiers.

  • 由于您已经知道您要使用的记录类型,因此请不要降级为匿名record,请使用众所周知的类型开头: “TraderMonthOutstanding”。

  • 就像您已经被告知的那样,RETURN返回的类型必须与您声明的RETURNS相匹配。由于您want only TraderId,请相应地调整RETURNS。如果要从现有表派生它,可以使用显示的语法。 Details in the manual.或者您可以插入实际类型。像integer或其他什么。

  • 由于您在制作表格时似乎一直使用双引号CaMeL案例名称,因此您必须继续使用它们:双引号 - 即使是函数体中的派生类型:

    RETURN NEXT r."TraderId";

看看我对“LoaDed Footgun”的意思?