概述
使用DECLARE定义一个游标, 游标可以被用来在大型查询暂停时检索少量的行。游标被创建后,可以用FETCH从中取得行。
游标是系统为用户开设的一个数据缓冲区,存放SQL语句的执行结果。游标的一个常见用途就是保存查询结果,以便以后使用。游标的结果集是由SELECT语句产生,如果处理过程需要重复使用一个记录集,那么创建一次游标而重复使用若干次,比重复查询数据库要快的多。

游标使用
SQL命令级
postgres=# begin; --开启事务BEGINpostgres=# declare mycur cursor for select * from user_info;--打开游标DECLARE CURSORpostgres=# fetch first from mycur;--取第一行数据userid | name | birthday | crt_time--------+--------+------------+----------------------------1 | abcdef | 2015-08-10 | 2021-07-05 23:03:00.239366(1 row)postgres=# fetch next from mycur;--取下一行数据userid | name | birthday | crt_time--------+--------+------------+---------------------------2 | abcdef | 2015-08-10 | 2021-07-05 23:03:00.23952(1 row)postgres=# move last in mycur; --游标移动到行尾MOVE 1postgres=# close mycur;关闭游标CLOSE CURSORpostgres=# commit;提交COMMIT
PL/pgSQL函数内使用
postgres=# create function my_cur(refcursor) returns refcursor as $$postgres$# beginpostgres$# open $1 for select * from user_info;postgres$# return $1;postgres$# end;postgres$# $$language plpgsql;CREATE FUNCTIONpostgres=# begin;BEGINpostgres=# select my_cur('test');my_cur--------test(1 row)postgres=# fetch first from test;userid | name | birthday | crt_time--------+--------+------------+----------------------------1 | abcdef | 2015-08-10 | 2021-07-05 23:03:00.239366(1 row)
源码导读
src/backend/tcop/pquery.c/** 对于Portals(客户端请求),有几种执行策略,具体取决于要执行什么查询。* (注意:无论什么情况下,一个Portal只执行一个source-SQL查询,因此从用户的角度来看只产生一个结果。* 但是,规则重写器可以将单个源查询扩展为零或多个实际查询。** PORTAL_ONE_SELECT: 包含一个SELECT查询。* 按需要的结果重复(递增)地运行执行器。* 该策略还支持可持有游标(执行器结果可以在事务完成后转储到tuplestore中进行访问)。** PORTAL_ONE_RETURNING: 包含一个带有RETURNING子句的INSERT/UPDATE/DELETE查询(可能还包括由规则重写添加的辅助查询)。* 在第一次执行时,运行Portal来完成并将主查询的结果转储到Portal的tuplestore中;* 然后根据需要将结果返回给客户端。* (我们不能支持半途中断的查询,因为AFTER触发器代码无法处理,* 也因为不想冒执行所有辅助查询失败的风险)。** PORTAL_ONE_MOD_WITH: 只包含一个SELECT查询,但它具有数据修改的CTEs。* 这与PORTAL_ONE_RETURNING的情况相同,因为可能需要触发触发器。将来它的行为可能更像PORTAL_ONE_SELECT。** PORTAL_UTIL_SELECT: 包含一个实用程序语句,该语句返回一个类似SELECT的结果(例如,EXPLAIN或SHOW)。* 在第一次执行时,运行语句并将其结果转储到portal tuplestore;然后根据需要将结果返回给客户端。** PORTAL_MULTI_QUERY: 除上述情况外的其他情况。* 在这里,不支持部分执行:Portal的查询语句将在第一次调用时运行到完成。*/typedef enum PortalStrategy{PORTAL_ONE_SELECT,PORTAL_ONE_RETURNING,PORTAL_ONE_MOD_WITH,PORTAL_UTIL_SELECT,PORTAL_MULTI_QUERY} PortalStrategy;/* Features/options */PortalStrategy strategy; /* 场景;see above */int cursorOptions; /* DECLARE CURSOR选项位;DECLARE CURSOR option bits */bool run_once; /* 是否只执行一次;portal will only be run once */* 在这里,为持有的游标或PORTAL_ONE_RETURNING或PORTAL_UTIL_SELECT存储元组。* (在事务结束后持有的游标不再具有任何活动执行器状态。)Tuplestorestate *holdStore; /* 存储持有的游标信息;store for holdable cursors */MemoryContext holdContext; /* 持有holdStore的内存上下文;memory containing holdStore *///用于表示的数据,主要由pg_cursors系统视图使用TimestampTz creation_time; /* portal定义的时间;time at which this portal was defined */bool visible; /* 是否在pg_cursors中可见? include this portal in pg_cursors? */* 游标可滚动,执行器需要支持REWIND和向后的扫描if (portal->cursorOptions & CURSOR_OPT_SCROLL)myeflags = eflags | EXEC_FLAG_REWIND | EXEC_FLAG_BACKWARD;elsemyeflags = eflags;
参考
https://www.postgresql.org/docs/current/sql-declare.html
http://postgres.cn/docs/12/sql-declare.html
文章转载自CP的PostgreSQL厨房,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。




