4

我有以下函数用于从表中检索一批 Id。OFFSET由于andLIMIT子句似乎提供了较差的性能,因此正在使用此功能。

CREATE OR REPLACE FUNCTION getBatch(_workloadId VARCHAR, _offSet INT, _limit INT)
  RETURNS SETOF NUMERIC AS $$
DECLARE 
    c SCROLL CURSOR FOR
      SELECT id FROM workload WHERE workload_id = $1 ORDER BY id ASC; 
BEGIN

OPEN c;
MOVE FORWARD $2 IN c; 
RETURN QUERY FETCH FORWARD 10 FROM c;

END;
$$ LANGUAGE plpgsql;

我希望将FETCH FORWARDcount其作为参数传递,但我无法找到执行此操作的方法。引用 $3 不起作用,我还尝试了以下方法:

EXECUTE 'RETURN QUERY FETCH FORWARD ' || $3 || ' FROM c;';

任何帮助将不胜感激。

4

1 回答 1

3

您将SQL 游标PL/pgSQL 游标混淆了,它们相似但不相同。特别是FETCH FORWARDcountplpgsql中没有:

方向子句可以是 SQLFETCH命令中允许的任何变体,除了可以获取多行的变体;即,它可以是NEXT, PRIOR, FIRST, LAST, ABSOLUTEcount, RELATIVEcount, FORWARD, 或BACKWARD.

在 plgpsql 中,您一次只能获取一行并处理(或返回)它。手册中还有免责声明

注意:本页描述了 SQL 命令级别的游标的使用。如果您尝试在 PL/pgSQL 函数中使用游标,则规则是不同的。

您可以在 plpgsql 中打开该游标并循环返回 rows。但这仅在您想从大光标中获取多个不同的部分以节省开销时才相关。否则一个普通的FOR循环(带有自动光标)或一个简单SELECT的 with OFFSETandLIMIT肯定会更快。游标主要是为了返回给客户端并由客户端使用:

CREATE OR REPLACE FUNCTION getbatch_ref(_cursor refcursor, _workload_id text)
  RETURNS refcursor AS
$func$
BEGIN
OPEN $1 SCROLL FOR
   SELECT id
   FROM   workload
   WHERE  workload_id = $2
   ORDER  BY id; 

   RETURN $1;
END
$func$ LANGUAGE plpgsql;

您可以在 SQL 中使用此函数:

BEGIN;
SELECT getbatch_ref('c', 'foo');
MOVE  FORWARD 10 IN c; 
FETCH FORWARD 10 FROM c;

ROLLBACK; -- or COMMIT;

你也可以只使用普通的 SQL:

BEGIN;
DECLARE c SCROLL CURSOR FOR
   SELECT id
   FROM   workload
   WHERE  workload_id = 'foo'
   ORDER  BY id; 

-- OPEN c; -- only relevant in plpgsql
-- The PostgreSQL server does not implement an OPEN statement for cursors;
-- a cursor is considered to be open when it is declared. 
MOVE  FORWARD 10 IN c; 
FETCH FORWARD 10 FROM c;

ROLLBACK; -- or COMMIT;
于 2013-03-15T01:28:18.973 回答