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.mzph.cn/diannao/69404.shtml

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

相关文章

Linux 快速对比两个文件的差异值

Linux 快速对比两个文件的差异值(无需排序、直接输出) 在日常开发或数据处理中,若需快速对比两个文本文件中的差异值(仅保留第一个文件中的独有内容),Linux 系统提供了两种高效方法。以下是具体操作及适用…

语言月赛 202308【小粉兔做麻辣兔头】题解(AC)

》》》点我查看「视频」详解》》》 [语言月赛 202308] 小粉兔做麻辣兔头 题目描述 粉兔喜欢吃麻辣兔头,麻辣兔头的辣度分为若干级,用数字表示,数字越大,兔头越辣。为了庆祝粉兔专题赛 #1 的顺利举行,粉兔要做一些麻…

C++20导出模块及使用

1.模块声明 .ixx文件为导入模块文件 math_operations.ixx export module math_operations;//模块导出 //导出命名空间 export namespace math_ {//导出命名空间中函数int add(int a, int b);int sub(int a, int b);int mul(int a, int b);int div(int a, int b); } .cppm文件…

使用redis实现 令牌桶算法 漏桶算法

流量控制算法,用于限制请求的速率。 可以应对缓存雪崩 令牌桶算法 核心思想是: 有一个固定容量的桶,里面存放着令牌(token)。每过一定时间(如 1 秒),桶中会自动增加一定数量的令牌…

活动预告 | 解锁 Excel 新境界 —— AI 技术赋能下的数据分析超级引擎!

课程介绍 在 AI 技术的浪潮中,Microsoft Excel 已经焕然一新,它不再仅仅是海量复杂数据的处理中心,更是未来趋势的预测大师。智能 Copilot 副驾驶的加入,让 Excel 如虎添翼,成为每一位数据探索者梦寐以求的超级引擎。在…

在阿里云ECS上一键部署DeepSeek-R1

DeepSeek-R1 是一款开源模型,也提供了 API(接口)调用方式。据 DeepSeek介绍,DeepSeek-R1 后训练阶段大规模使用了强化学习技术,在只有极少标注数据的情况下提升了模型推理能力,该模型性能对标 OpenAl o1 正式版。DeepSeek-R1 推出…

如何通过Deepseek的API进行开发和使用(适合开发者和小白的学习使用教程)

目录 一,API创建与获取 二,直接进行API的调用 2.1 安装第三方库 2.2 官方支持的接口调用方式 2.3 编写的小tips 2.4 AI助手工具代码 三, 配置方面的说明 3.1 token价格和字符用量 3.2 响应错误码 最近在休息的时候也是一直会刷到关于deepseek,简单使用了一下,发现这…

unity学习33:角色相关2,碰撞检测,collider 和 rigidbody,测试一个简单碰撞爆炸效果

目录 1 给gameObject添加rigidbody 2 rigidbody的属性 2.1 基础属性 2.2 插值 详细 2.3 碰撞检测 2.4 constraints 冻结坐标轴的移动和旋转 2.5 layer Overrides 3 碰撞检测 collision Detection 3.1 每个gameObeject上都会创建时自带一个 Collider 3.2 Collider的绿…

【生成模型之十四】Visual Autoregressive Modeling

论文:Visual Autoregressive Modeling: Scalable Image Generation via Next-Scale Prediction code:GitHub - FoundationVision/VAR: [NeurIPS 2024 Best Paper][GPT beats diffusion🔥] [scaling laws in visual generation📈]…

硬核技术:小程序能够调用手机的哪些传感器

一、加速度传感器 小程序可以调用手机的加速度传感器来检测设备的运动状态。加速度传感器能够测量设备在三个轴(X、Y、Z)上的加速度变化。通过分析这些数据,小程序可以实现一些功能,如运动检测、步数统计、游戏中的动作感应等。 健…

活动预告 |【Part 2】Microsoft 安全在线技术公开课:通过扩展检测和响应抵御威胁

课程介绍 通过 Microsoft Learn 免费参加 Microsoft 安全在线技术公开课,掌握创造新机遇所需的技能,加快对 Microsoft Cloud 技术的了解。参加我们举办的“通过扩展检测和响应抵御威胁”技术公开课活动,了解如何更好地在 Microsoft 365 Defen…

【WB 深度学习实验管理】利用 Hugging Face 实现高效的自然语言处理实验跟踪与可视化

本文使用到的 Jupyter Notebook 可在GitHub仓库002文件夹找到,别忘了给仓库点个小心心~~~ https://github.com/LFF8888/FF-Studio-Resources 在自然语言处理领域,使用Hugging Face的Transformers库进行模型训练已经成为主流。然而,随着模型复…

创建一个javaWeb Project

文章目录 前言一、eclipse创建web工程二、web.xmlservlet.xml< mvc:annotation-driven/ > Spring MVC 驱动< context:component - scan >&#xff1a;扫描< bean > ... < /bean >< import > config/beans.xml beans.xmlmybatis.xml 前言 javaWe…

【蓝桥杯—单片机】第十一届省赛真题代码题解题笔记 | 省赛 | 真题 | 代码题 | 刷题 | 笔记

第十一届省赛真题代码部分 前言赛题代码思路笔记竞赛板配置内部振荡器频率设定键盘工作模式跳线扩展方式跳线 建立模板明确设计要求和初始状态显示功能部分数据界面第一部分第二部分第三部分调试时发现的问题 参数设置界面第一部分第二部分和第四部分第三部分和第五部分 按键功…

寒假2.7

题解 web&#xff1a;[HCTF 2018]WarmUp 打开是张表情包 看一下源代码 访问source.php&#xff0c;得到完整代码 代码审计 <?phphighlight_file(__FILE__);class emmm{public static function checkFile(&$page){$whitelist ["source">"source.p…

python康威生命游戏的图形化界面实现

康威生命游戏&#xff08;Conway’s Game of Life&#xff09;是由英国数学家约翰何顿康威&#xff08;John Horton Conway&#xff09;在1970年发明的一款零玩家的细胞自动机模拟游戏。尽管它的名字中有“游戏”&#xff0c;但实际上它并不需要玩家参与操作&#xff0c;而是通…

【数据结构】链表应用-链表重新排序

重新排序 反转链表预期实现思路解题过程code力扣代码核心代码完整代码 总结 删除链表中间节点代码解惑 链表重新排序题目描述解题思路解题过程复杂度代码力扣代码完整代码 反转链表 预期实现 思路 你选用何种方法解题&#xff1f; 我选用了迭代法来反转链表。这是一种经典且高…

pytest-xdist 进行多进程并发测试!

在软件开发过程中&#xff0c;测试是确保代码质量和可靠性的关键步骤。随着项目规模的扩大和复杂性的增加&#xff0c;测试用例的执行效率变得尤为重要。为了加速测试过程&#xff0c;特别是对于一些可以并行执行的测试用 例&#xff0c;pytest-xdist 提供了一种强大的工具&…

mysql8安装时提示-缺少Microsoft Visual C++ 2019 x64 redistributable

MySQL8.0安装包mysql-8.0.1-winx64进行安装&#xff0c;提示&#xff1a;This application requires Visual Studio 2019 x64Redistributable, Please install the Redistributable then runthis installer again。出现这个错误是因为我们电脑缺少Microsoft Visual C 这个程序&…

【MySQL】深度理解事务的隔离性:全面讲解事务的四种隔离级别

**前言&#xff1a;**上节内容我们主要说了如果没有设置保存点&#xff0c; 也可以回滚&#xff0c;但是只能回滚到事务的开始。直接使用rollback的前提是事务还没有提交。并且如果一个事务被提交了&#xff0c;就不可以回退。同时我们也可以使用savepoint设置回滚点。 可以自己…