在 PL/pgSQL 中实现游标功能作为分页

Posted

技术标签:

【中文标题】在 PL/pgSQL 中实现游标功能作为分页【英文标题】:Implement cursor function as pagination in PL/pgSQL 【发布时间】:2021-11-16 06:23:37 【问题描述】:

我有超过 1000 行的电影表。每次调用 psql 函数时,我都需要获取 5 行。在函数中,如果参数为空,我将有参数,它应该返回前 5 行,否则接下来的 5 行带有我传递的参数

code  |          title          | did | date_prod  |   kind   |  len
-------+-------------------------+-----+------------+----------+-------
 BL101 | The Third Man           | 101 | 1949-12-23 | Drama    | 01:44
 BL102 | The African Queen       | 101 | 1951-08-11 | Romantic | 01:43
 JL201 | Une Femme est une Femme | 102 | 1961-03-12 | Romantic | 01:25
 P_301 | Vertigo                 | 103 | 1958-11-14 | Action   | 02:08
 P_302 | Becket                  | 103 | 1964-02-03 | Drama    | 02:28

create or replace function get_giusers_batch(code)
   returns void as $$
declare 
    user_batch record;
     giusers cursor 
         for select *
         from giuser;
begin
   -- open the cursor
   open giusers(code);
    
   
-- fetch row into the film
  user_batch := fetch FORWARD 10 FROM giusers;
-- exit when no more row to fetch
  exit when not found;

 
   
  
   -- close the cursor
   close giusers;

   return user_batch;
end; $$

【问题讨论】:

创建一个游标,然后让函数从该游标中获取 5 行。 BEGIN WORK; DECLARE films_cur SCROLL CURSOR FOR SELECT * FROM film; -- Fetch the first 5 rows in the cursor films_cur: fetch FORWARD 10 FROM films_cur; -- Close the cursor and end the transaction: CLOSE films_cur; COMMIT WORK;@LaurenzAlbe 这是正确的吗? 【参考方案1】:

如果你想分页,你的意思是用户交互。在此期间您无法保持事务处于打开状态,因此您需要一个 WITH HOLD 游标。为此,您需要 PL/pgSQL 中的动态 SQL。明确关闭游标很重要!

这是一个例子:

CREATE FUNCTION get_data(arg integer) RETURNS SETOF uni
   LANGUAGE plpgsql VOLATILE CALLED ON NULL INPUT AS
$$BEGIN
   IF arg IS NOT NULL THEN
      /* make sure cursor is closed */
      BEGIN
         EXECUTE 'CLOSE get_data_cur';
      EXCEPTION
         WHEN invalid_cursor_name THEN
            NULL;  /* ignore */
      END;

      /* declare and open cursor */
      EXECUTE format(
                 E'DECLARE get_data_cur CURSOR WITH HOLD FOR\n'
                 'SELECT id FROM uni\n'
                 'WHERE id > %s',
                 arg
              );
   END IF;

   /* return next five rows */
   RETURN QUERY EXECUTE 'FETCH 5 FROM get_data_cur';

   /* close cursor when we are done */
   IF NOT FOUND THEN
      EXECUTE 'CLOSE get_data_cur';
   END IF;
END;$$;

【讨论】:

以上是关于在 PL/pgSQL 中实现游标功能作为分页的主要内容,如果未能解决你的问题,请参考以下文章

游标可以在 PL/pgSQL 中保存变量吗?

用于行 mod 3 的 PL/pgSQL 游标

PL/pgSQL 中 PL/SQL %NOTFOUND 的等价物是啥?

DevExpress中实现GridControl的分页功能

PL/pgSQL 代码的问题

SwiftUI Firestore 查询游标分页不起作用