sql - postgresql 迭代n条记录

标签 sql postgresql plpgsql postgresql-9.4 postgresql-9.5

我有表student_list,它仅包含student_id一列和100行。 我需要同时获取10-10条记录,然后执行一些操作。

 CREATE OR REPLACE FUNCTION loop_fetch()
  RETURNS void AS
$BODY$
DECLARE
myrow student_list%rowtype;
cur1 CURSOR FOR SELECT * FROM student_list ;
BEGIN
 OPEN cur1;
    LOOP
    -- i need to fetch rows based on limit
    FETCH NEXT 10 FROM cur1 INTO myrow;
        exit when myrow  IS NULL;
        INSERT INTO new_tbl SELECT myrow.student_id ;
    END LOOP;
    CLOSE cur1;  
END;
$BODY$
  LANGUAGE plpgsql VOLATILE;

实现此方法的任何建议 - FETCH NEXT 5 FROM cur1 INTO myrow

最佳答案

你的代码不应该工作。 FETCH NEXT 10 从游标中获取 10 行,但 INTO 子句仅获取第一行,其他行都会丢失。 MyRow 是复合变量 - 它只能保存一行。

我收到一个错误:

ERROR:  FETCH statement cannot return multiple rows
LINE 6:   fetch 10 from r into re;
          ^

这是正确的结果。

简短且可能是最正确的解决方案是使用FOR IN SELECT。该语句在内部使用游标,并且在第一次迭代中获取 10 行,在其他迭代中获取 50 行。

所以:

DECLARE r record;
BEGIN
  FOR r IN SELECT * FROM student_list 
  LOOP
    INSERT INTO newtbl VALUES(r.*);
  END LOOP;
END;

几乎可以完成您想要的所有操作。

如果你想显式地使用游标(并且确实想以 block 的方式获取),则需要使用更多的周期。下面的代码有点奇怪,我在这里写它只是为了教育 - 不要认为它对实际生活有任何好处。

CREATE OR REPLACE FUNCTION loop_fetch()
RETURNS void AS
$BODY$
DECLARE
 myrow student_list%rowtype;
 cur1 CURSOR FOR SELECT * FROM student_list ;
 rows int DEFAULT 0;
BEGIN
  LOOP
    -- i need to fetch rows based on limit
    FOR myrow IN cur1
    LOOP
      INSERT INTO new_tbl SELECT myrow.student_id ;
    END LOOP;
    EXIT WHEN NOT FOUND;
    rows := rows + 1;
    EXIT WHEN rows = 10;
  END LOOP;
END;
$BODY$
LANGUAGE plpgsql VOLATILE;

这段代码应该可以工作,但它很疯狂。

或者您可以使用FOR IN EXECUTE

do $$
declare
  c cursor for select * from generate_series(1,100);
  r record;
begin
  -- *** UGLY CODE, DON'T DO IT!!! ***
  open c;
  -- iteration over FETCH is possible only via
  -- dynamic SQL. FOR statement uses FETCH internally
  -- by default, and is nonsense use FETCH 2x
  for r in execute 'fetch 10 from c'
  loop
    raise notice '%', r;
  end loop;
  close c;
  -- *** UGLY CODE, DON'T DO IT!!! ***
end;
$$;

内部FOR IN 查询使用游标。所以 FOR IN EXECUTE FETCH 是通过游标从另一个游标读取,这是性能废话,而且代码非常丑陋。

重要的事情 - PostgreSQL 没有表格变量 - 因此您不能为一个变量分配更多行,也不能从一个变量填充更多行。

但是您的请求看起来像是过早的优化。最快速、最有效的是命令:

INSERT INTO newtbl SELECT studentId FROM student_list

SQL可以很好地处理大量操作。 1M 行不算什么。 仅在确实需要时才使用光标

关于sql - postgresql 迭代n条记录,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51497593/

相关文章:

mysql - LOAD DATA INFILE - 以字符终止的字段,该字符也出现在字段中

sql - 将多个查询结果合并到一张表中,结果顺序是如何确定的?

sql - COPY 动态文件名

xml - 在 PostgreSQL 数据库中存储 XML 解释计划

sql - 防止展平 View 后重新排序

sql - 从自然连接中排除列

SQL 加入多个匹配条件

sql - 将多行转换为多列的一行

python - 如何使用 GROUP BY 和 HAVING 与 SQLAlchemy 和 Postgresql 获取具有最大更新日期时间的行

sql - 如何在 SQL 中打印到控制台?