数据库游标

9.1.    游标的定义
定义游标:
DECLARE cur_Categories INSENSITIVE CURSOR
FOR SELECT CategoryID,CategoryName FROM Categories;
从游标中检索行的操作称为提取。提取选项如下:
?    FETCH FIRST  提取游标中的第一行。
?    FETCH NEXT   提取上次提取行之后的行。
?    FETCH PRIOR  提取上次提取行之前的行。
?    FETCH LAST     提取游标中的最后一行。
?    FETCH ABSOLUTE n
如果 n 为正整数,则提取游标中从第 1 行开始的第 n 行。如果 n 为负整数,则提取游标中的倒数第 n 行。如果 n 为 0,则没有行被提取。
?    FETCH RELATIVE n
提取上次所提取行之后的第 n 行。如果 n 为正数,则提取所上次提取行之后的第 n 行。如果 n 为负数,则提取上次所提取行之前的第 n 行。如果 n 为 0,则同一行被再次提取。
9.2.    检索游标

DECLARE Teacher_Cursor SCROLL CURSOR
FOR
SELECT tname,dname,age FROM Teacher ORDER BY age
OPEN Teacher_Cursor --打开游标
DECLARE @T_Name CHAR(12),@T_Department CHAR(12),@T_Age INT
FETCH LAST FROM Tracher_Cursor INTO @T_Name,@T_Department,@T_Age --跳到最后一行
PRINT @T_Name + @T_Department + CAST(@T_Age AS CHAR(2))
FETCH PRIOR FROM Tracher_Cursor INTO @T_Name,@T_Department,@T_Age --跳到倒数第二行
PRINT @T_Name + @T_Department + CAST(@T_Age AS CHAR(2))

DECLARE @CategoryId Int
DECLARE @CategoryName Varchar(50)
OPEN cur_Categories
FETCH NEXT FROM cur_Categories INTO @CategoryId,@CategoryName
WHILE @@Fetch_Status = 0
BEGIN
PRINT '品种ID:' + @CategoryId + '产品名称:' + @CategoryName
FETCH NEXT FROM cur_Categories INTO @CategoryId,@CategoryName
END

 

9.3.    基于游标的DELETE
语法如下:

DELETE FROM table_name WHERE CURRENT OF cursor_name
 

注:
1、    WHERE子句必须与CURRENT OF一起使用,用来确定打开的游标。
2、    如果游标的SELECT子句中包含有ORDER BY子句,DBMS将把游标限定为READ ONLY,因此不能在相同的游标SELECT语句中同时有ORDER BY和FOR UPDATE语句。

DECLARE BoyTeacher_Cursor CURSOR
FOR
SELECT * FROM TEACHER WHERE TSEX='male'
FOR UPDATE --说明游标可更新
OPEN BoyTeacher_Cursor
FETCH FROM BoyTeacher_Cursor
DELETE FROM TEACHER WHERE CURRENT OF BoyTeacher_Cursor --删除第一行
FETCH FROM BoyTeacher_Cursor
FETCH FROM BoyTeacher_Cursor
DELETE FROM TEACHER WHERE CURRENT OF BoyTeacher_Cursor --删除第三行
CLOSE BoyTeacher_Cursor
 



9.4.    基于游标的UPDATE

语法:UPDATE table_name SET WHERE CURRENT OF cursor_name
 

 

DECLARE GrilTeacher_Cursor CURSOR
FOR
SELECT SAL FROM TEACHER WHERE TSEX='female'
FOR UPDATE --说明游标可更新
DECLARE @Avg_Sal INT,@T_Sal INT
SELECT @Avg_Sal = AVG(SAL) FROM TEACHER WHERE TSEX='female'
OPEN GrilTeacher_Cursor
FETCH FROM GrilTeacher_Cursor
INTO @T_Sal
WHERE @@FETCH_STATUS = 0 --FETCH执行成功
BEGIN
    IF @T_Sal IS NULL
     UPDATE TEACHER SET SAL = @Avg_Sal
     WHERE CURRENT OF GrilTeacher_Cursor
     FETCH FROM GrilTeacher_Cursor INTO @T_Sal--游标下移一条记录
END
CLOSE GrilTeacher_Cursor
 





9.5.    游标的调用

DECLARE cur_Categories INSENSITIVE CURSOR
FOR SELECT CategoryID,CategoryName FROM Categories;
 






9.6.    游标的关闭

CLOSE cur_Categories
 


9.7.    游标的删除

DEALLOCATE cur_Categories
 

 

### 数据库游标使用教程 数据库游标是一种临时的数据结构,允许用户逐访问查询结果集。以下是关于数据库游标使用的详细介绍: #### 游标的定义与作用 游标提供了一种机制来遍历和操作来自数据库的结果集。通过游标可以实现对每一条记录的操作,而不是一次性加载整个结果集到内存中[^1]。 #### 创建与关闭游标 创建游标的过程一般分为以下几个部分: - **声明游标**:指定要执的 SQL 查询语句。 - **打开游标**:执查询并填充结果集。 - **提取数据**:逐一读取每一数据。 - **关闭游标**:释放资源以防止内存泄漏。 在 GaussDB 中,`SQL%NOTFOUND` 属性可用于检测最近一次 SQL 操作是否未找到任何匹配项。这有助于开发者判断何时停止循环或者采取其他措施。 对于 DB2 数据库而言,其游标的语法与其他关系型数据库相似,但也有一些特定的功能支持,比如动态 SQL 和参数化查询的支持[^2]。 而在 Python 编程环境中连接 PostgreSQL 时,默认情况下会禁用服务器端游标 (`DISABLE_SERVER_SIDE_CURSORS`),这意味着客户端需要显式启用它们才能利用更高效的分页功能[^3]。 #### 示例代码展示如何使用游标 下面分别给出几种常见场景下的游标使用例子: ##### 针对 GaussDB 的简单示例 ```sql DECLARE cursor_name CURSOR FOR SELECT * FROM table_name; OPEN cursor_name; FETCH NEXT FROM cursor_name INTO @variable1, @variable2; -- 提取单条记录至变量 IF SQL%NOTFOUND THEN -- 如果没有更多记录则退出 CLOSE cursor_name; END IF; ``` ##### 关于 DB2 的复杂情况处理 当涉及到大量数据检索时,在 DB2 上可以通过设置隔离级别以及预分配缓冲区大小等方式优化性能表现: ```sql SET CURRENT ISOLATION UR; -- 设置事务隔离等级为 Uncommitted Read 减少锁冲突 DECLARE c_scroll CURSOR WITH RETURN TO CLIENT AS SELECT ... WHERE ... FOR FETCH ONLY SCROLLABLE DYNAMIC ROWSET SIZE 50; -- 定义滚动光标及每次获取数量 ``` ##### 利用 psycopg2 库操控 PostgreSQL (Python) 如果是在 Python 脚本里调用 Postgres,则需注意调整配置以便更好地控制大表扫描过程: ```python import psycopg2 conn = psycopg2.connect("dbname=test user=postgres password=secret") cur = conn.cursor('unique_cursor_name') # 启动服务端游标模式 try: cur.execute("SELECT * FROM large_table") while True: records = cur.fetchmany(size=100) if not records: break except Exception as e: print(f"Error occurred {e}") finally: cur.close() conn.commit() ``` ### 常见问题解答 1. **为什么我的程序运缓慢?** 当面对超大规模表格时如果没有合理运用索引或是忽略了适当范围限定条件的话很容易造成效率低下现象发生。另外也要考虑是否存在死锁状况等问题存在^. 2. **怎样判定当前是否有可用的新纪录待读取呢?** 可借助像 `SQL%ROWCOUNT`, 或者针对不同平台各自特有的标志位来进状态监控如上述提到过的 `%NOTFOUND`. 3. **能否举例说明下实际项目里的应用实例吗 ?** 实际开发过程中经常会遇到批量导入导出需求或者是某些特殊业务逻辑要求单独对待每一个实体对象的情形此时恰当地引入游标概念往往能够简化编码难度同时提升可维护程度.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值