使用plpgsql进行FOR LOOP控件中的SELECT子句

时间:2015-05-14 20:45:14

标签: postgresql select for-loop plpgsql

我尝试制作一个脚本,输出只有一个用户使用的所有foos,如果foo被多个用户使用,则不应该输出。

这是我的桌子

foos  (id, value)
users (id, name)
used  (foo_id, user_id)

和我的工作脚本

FUNCTION output_unshared_foos ()
RETURNS foos AS
$a$
DECLARE
  foocounts RECORD;
BEGIN
  SELECT u.foo_id, count(*)
  INTO foocounts -- store in the local variable
  FROM used u
  GROUP BY u.foo_id;

  FOR f IN SELECT * FROM foos
  LOOP
    IF (SELECT fc.count < 2 FROM foocounts fc WHERE fc.foo_id = f.id) THEN
      RETURN NEXT f;
    END IF;
  END LOOP;
END
$a$ language plpgsql;

似乎不起作用,返回每一行,条件控制似乎总是正确。

1 个答案:

答案 0 :(得分:0)

您的第一个问题是您无法将返回多行的查询结果存储到单个变量(SELECT u.foo_id, count(*) INTO ...部分)中。当你调用你的函数时,我很惊讶你没有遇到运行时错误。

您的函数也无法编译,因为未声明记录f且定义为returns foos的函数无法使用return next

但你的方法是错误的(即使它有效)。在SQL中,逐行处理几乎总是错误的选择。 SQL和关系数据库用于处理集合,而不是单行。

您的问题可以通过一个查询解决:

select foo_id
from used
group by foo_id
having count(distinct user_id) = 1

将返回仅由一个用户使用的所有foo ID。

如果您需要foos表中的其他信息,可以将上述查询加入到foos表中:

select f.*
from foos f
  join (
     select foo_id
     from used
     group by foo_id
     having count(distinct user_id) = 1
  ) u on f.id = u.foo_id