postgresql 游标(cursor)的使用

概述

PostgreSQL游标可以封装查询并对其中每一行记录进行单独处理。当我们想对大量结果集进行分批处理时可以使用游标,因为一次性处理可能造成内存溢出。

另外我们可以定义函数返回游标类型变量,这是函数返回大数据集的有效方式,函数调用者根据返回游标对结果进行处理。

下图展示了如何使用PostgreSQL游标:

  1. 第一步声明游标.
  2. 接着打开游标.
  3. 然后从结果中取出行至目标变量中.
  4. 之后,检查是否有更多的行可以继续取。如何有返回第三步,否则至第五步.
  5. 最后,关闭游标.

下面章节我们会详细说明每一步。

声明游标

为了访问游标,需要在声明块中声明游标变量。PostgreSQL提供了特定类型REFCURSOR 用于声明游标变量。下面示例声明非绑定游标:

DECLARE 
   my_cursor REFCURSOR;

另一种方式声明绑定游标变量,及声明时绑定查询语句,语法如下:

cursor_name [ [NO] SCROLL ] CURSOR [( name datatype, name data type, ...)] FOR query;

首先,指定游标变量名称。接着,使用SCROLL指定游标是否可以回滚。如果使用 NO SCROLL,游标不能回滚。然后是CURSOR关键字,其后是逗号分隔的参数列表(name datatype) ,用于定义查询参数。这些参数在游标打开是被替换。之后指定查询在FOR 关键字之后,看使用任何有效的SELECT子句。

首先,指定游标变量名称。接着,使用SCROLL指定游标是否可以回滚。如果使用 NO SCROLL,游标不能回滚。然后是CURSOR关键字,其后是逗号分隔的参数列表(name datatype) ,用于定义查询参数。这些参数在游标打开是被替换。之后指定查询在FOR 关键字之后,看使用任何有效的SELECT子句。

下面示例如何声明游标变量:

DECLARE
    cur_films  CURSOR FOR SELECT * FROM film;
    cur_films2 CURSOR (year integer) FOR SELECT * FROM film WHERE release_year = year;

 

cur_films是封装film表中所有记录的游标变量。
cur_films2是封装film表中带有特定发行年份记录的游标变量。

绑定游标变量被初始化为字符串值表示其名称(官方文档成为portal name),后续一致不变。但非绑定游标变量初始缺省为null值,所以后期会接受一个自动生成的唯一名称。

当递归函数中定义游标时,需定义为非绑定游标,否则会产生错误:cursor already in use。

## 打开游标

游标在使用之前必须要打开,PostgreSQL提供特定语法用于打开绑定游标和非绑定游标。

打开非绑定游标

打开非绑定游标语法:

OPEN  unbound_cursor_variable [ [ NO ] SCROLL ] FOR query;

因为非绑定游标变量在声明时没有绑定任何查询,因此在打开时必须指定查询。请看示例:

OPEN my_cursor FOR SELECT * FROM city WHERE counter = p_country;

PostgreSQL 可以打开游标并绑定至动态查询,语法如下:

OPEN unbound_cursor_variable[ [ NO ] SCROLL ] 
FOR EXECUTE query_string [USING expression [, ... ] ];

在下面示例中,我们构建动态查询基于sort_field参数对结果进行排序,然后打开游标并执行动态查询:

query := 'SELECT * FROM city ORDER BY $1';
 
OPEN cur_city FOR EXECUTE query USING sort_field; 

打开绑定游标

因为绑定游标声明时已经绑定了查询,所以打开时,仅需要传入必要参数即可:

OPEN cursor_variable[ (name:=value,name:=value,...)];

下面示例中,打开上节声明的绑定游标cur_films和cur_films2:

OPEN cur_films;
OPEN cur_films2(year:=2005);

 

使用游标

打开游标之后,可以使用FETCH, MOVE操纵游标,并更新或删除记录。
取下一行记录语法:

FETCH [ direction { FROM | IN } ] cursor_variable INTO target_variable;

fetch语句从游标中获得下一行记录并赋值给目标变量target_variable,可以是record类型或row变量或逗号分隔的变量列表。如果没有发现可取行,目标变量target_variable为null。

如果不显示指定方向,方向缺省为NEXT。可以有下面值:

  • NEXT
  • LAST
  • PRIOR
  • FIRST
  • ABSOLUTE count
  • RELATIVE count
  • FORWARD
  • BACKWARD

注意,使用SCROLL声明游标可以FORWARD 和 BACKWARD 。请看示例:

FETCH cur_films INTO row_film;
FETCH LAST FROM row_film INTO title, release_year;

 

移动游标

语法如下:

MOVE [ direction { FROM | IN } ] cursor_variable;

如果仅想移动游标并不返回行,可以使用move语句。方向关键字与FETCH语句一致。

MOVE cur_films2;
MOVE LAST FROM cur_films;
MOVE RELATIVE -1 FROM cur_films;
MOVE FORWARD 3 FROM cur_films;

删除或更新行

一旦游标位置确定,则可以删除或更新行,提供使用DELETE WHERE CURRENT OF 或 UPDATE WHERE CURRENT OF语句:

UPDATE table_name 
SET column = value, ... 
WHERE CURRENT OF cursor_variable;
 
DELETE FROM table_name 
WHERE CURRENT OF cursor_variable;

 请看示例:

UPDATE film SET release_year = p_year 
WHERE CURRENT OF cur_films;

 

关闭游标

关闭游标使用close关键字:

CLOSEC  cursor_variable;

close语句释放资源或释放游标变量使其可以被再次打开。

完整示例

下面的示例用于查询fooid为指定值的fooname首先创建表foo:

create table foo (
fooid int,
fooname text
)

插入数据,然后创建实例: 

create or replace function get_fooname1(id integer)
returns text as $$
declare
title text default 'fooname ';
f_name record;
cur_fname cursor(id integer)
for select fooname,fooid
from foo
where fooid=id;
begin
open cur_fname(id);
loop
fetch cur_fname into f_name;
exit when not found;
 
title := title || ':' ||f_name.fooname;
end loop;
close cur_fname;
return title;
end; $$
language plpgsql;

然后使用select语句可以查询: 

postgres=# select * from get_fooname1(1);
 get_fooname1
--------------
 fooname :hi
(1 row) 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/15310.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

十二、Docker Compose 部署 SpringCloudAlibaba 微服务

一、部署基础服务 0、项目部署结构 项目目录结构如下: /home/zhzl_hebei/ ├── docker-compose.yml └── geochance-auth/└── Dockerfile└── geochance-auth.jar └── geochance-system/└── Dockerfile└── geochance-system.jar └── geochance-gateway/…

java项目之金华学校社团管理系统源码(ssm+mysql)

项目简介 金华学校社团管理系统实现了以下功能: 金华学校社团管理系统的主要使用者管理员对系统用户、公告信息进行管理。对社团信息进行管理,审核报名,统计社团报名结果等。学生维护个人信息,查看本校的社团信息,对…

deepseek+kimi自动生成ppt

打开deepseek官网,输入详细的需求,让他生成个ppt 接着deepseek开始思考生成了 接着复制生成了的内容 打开kimi粘贴刚才deepseek生成的内容 可以一键生成啦,下载编辑使用吧

Shapefile格式文件解析和显示

Java实现GIS SHP文件格式的解析和显示,JDK19下编译,awt图形系统显示。 SHP文件对应的属性存储在DBF格式数据库中,解析见:DBASE DBF数据库文件解析_数据库文件在线解析-CSDN博客 解析SHP文件代码: public static Shap…

Golang 并发机制-7:sync.Once实战应用指南

Go的并发模型是其突出的特性之一,但强大的功能也带来了巨大的责任。sync.Once是由Go的sync包提供的同步原语。它的目的是确保一段代码只执行一次,而不管有多少协程试图执行它。这听起来可能很简单,但它改变了并发环境中管理一次性操作的规则。…

【DeepSeek × Postman】请求回复

新建一个集合 在 Postman 中创建一个测试集合 DeepSeek API Test,并创建一个关联的测试环境 DeepSeek API Env,同时定义两个变量 base_url 和 api_key 的步骤如下: 1. 创建测试集合 DeepSeek API Test 打开 Postman。点击左侧导航栏中的 Co…

如何通过PHP接入DeepSeek的API

想知道如何通过PHP接入DeepSeek的API。看起来他对之前的Python步骤比较熟悉,但这次想用PHP实现。 首先,我需要回顾一下DeepSeek API的文档,确认它支持哪些方法和参数。假设用户已经配置了环境变量,比如API密钥,接下来…

网络工程师 (26)TCP/IP体系结构

一、层次 四层: 网络接口层:TCP/IP协议的最底层,负责网络层与硬件设备间的联系。该层协议非常多,包括逻辑链路和媒体访问控制,负责与物理传输的连接媒介打交道,主要功能是接收数据报,并把接收到…

每日Attention学习22——Inverted Residual RWKV

模块出处 [arXiv 25] [link] [code] RWKV-UNet: Improving UNet with Long-Range Cooperation for Effective Medical Image Segmentation 模块名称 Inverted Residual RWKV (IR-RWKV) 模块作用 用于vision的RWKV结构 模块结构 模块代码 注:cpp扩展请参考作者原…

vscode预览插件

在左侧列表拓展里搜索 Live Preview 安装,然后在html页面点击右键找到show Preview 结果如下图 然后就可以进行代码开发并实时预览了

【04】Java+若依+vue.js技术栈实现钱包积分管理系统项目-若依框架二次开发准备工作-以及建立初步后端目录菜单列-优雅草卓伊凡商业项目实战

【04】Java若依vue.js技术栈实现钱包积分管理系统项目-若依框架二次开发准备工作-以及建立初步后端目录菜单列-优雅草卓伊凡商业项目实战 项目背景 本项目经费43000元,需求文档如下,工期25天,目前已经过了8天,时间不多了&#x…

【DeepSeek】DeepSeek概述 | 本地部署deepseek

目录 1 -> 概述 1.1 -> 技术特点 1.2 -> 模型发布 1.3 -> 应用领域 1.4 -> 优势与影响 2 -> 本地部署 2.1 -> 安装ollama 2.2 -> 部署deepseek-r1模型 1 -> 概述 DeepSeek是由中国的深度求索公司开发的一系列人工智能模型,以其…

Windows下AMD显卡在本地运行大语言模型(deepseek-r1)

Windows下AMD显卡在本地运行大语言模型 本人电脑配置第一步先在官网确认自己的 AMD 显卡是否支持 ROCm下载Ollama安装程序模型下载位置更改下载 ROCmLibs先确认自己显卡的gfx型号下载解压 替换替换rocblas.dll替换library文件夹下的所有 重启Ollama下载模型运行效果 本人电脑配…

使用Pytorch训练一个图像分类器

一、准备数据集 一般来说,当你不得不与图像、文本或者视频资料打交道时,会选择使用python的标准库将原始数据加载转化成numpy数组,甚至可以继续转换成torch.*Tensor。 对图片而言,可以使用Pillow库和OpenCV库对视频而言&#xf…

DeepSeek之Api的使用(将DeepSeek的api集成到程序中)

一、DeepSeek API 的收费模式 前言:使用DeepSeek的api是收费的 免费版: 可能提供有限的免费额度(如每月一定次数的 API 调用),适合个人开发者或小规模项目。 付费版: 超出免费额度后,可能需要按…

git fetch和git pull 的区别

git pull 实际上就是 fetch merge 的缩写, git pull 唯一关注的是提交最终合并到哪里(也就是为 git fetch 所提供的 destination 参数) git fetch 从远程仓库下载本地仓库中缺失的提交记录,并更新远程分支指针 git pull抓取更新再合并到本地分支,相当于…

信息科技伦理与道德3-2:智能决策

2.2 智能推荐 推荐算法介绍 推荐系统:猜你喜欢 https://blog.csdn.net/search_129_hr/article/details/120468187 推荐系统–矩阵分解 https://blog.csdn.net/search_129_hr/article/details/121598087 案例一:YouTube推荐算法向儿童推荐不适宜视频 …

[LVGL] 在VC_MFC中移植LVGL

前言: 0. 在MFC中开发LVGL的优点是可以用多个Window界面做辅助扩展【类似GUIguider】 1.本文基于VC2022-MFC单文档框架移植lvgl8 2. gitee上下载lvgl8.3 源码,并将其文件夹改名为lvgl lvgl: LVGL 是一个开源图形库,提供您创建具有易于使用…

[RabbitMQ] RabbitMQ常见面试题

🌸个人主页:https://blog.csdn.net/2301_80050796?spm1000.2115.3001.5343 🏵️热门专栏: 🧊 Java基本语法(97平均质量分)https://blog.csdn.net/2301_80050796/category_12615970.html?spm1001.2014.3001.5482 🍕 Collection与…

《qt easy3d中添加孔洞填充》

《qt easy3d中添加孔洞填充》 效果展示一、创建流程二、核心代码效果展示 参考链接Easy3D开发——点云孔洞填充 一、创建流程 创建动作,并转到槽函数,并将动作放置菜单栏,可以参考前文 其中,槽函数on_actionHoleFill_triggered实现如下: