SQL SERVER 从入门到精通 第5版 第三篇 高级应用 第12章 游标的使用 读书笔记

 第十二章 游标的使用

  >.游标的概述

  游标是一种数据库对象,用于在SQL中处理(SELECT的)查询结果集。它允许逐行地访问查询结果集的数据,以进行一系列操作,如更新、删除或插入数据。游标通常用于存储过程或触发器中,用于对数据进行逐行处理。通过游标,可以实现对结果集的逐行处理,可以方便地进行数据处理和操作。游标在数据库中的使用可能会导致性能问题,应该谨慎使用。

  >.游标的实现

  一个完整的游标由五个部分组成,并且遵循以下顺序:

    1.声明游标

    2.打开游标

    3.使用游标

    4.关闭游标

    5.释放游标

  >.游标的类型

    >.静态游标

      静态游标的结果集是保存在tempdb中的,相当于是对原数据的一个快照,只读,不能对原数据进行修改.不能看到数据的更新. 特点: 只读,消耗资源少,适用于数据量不大且不需要频繁更新的情况。

 

    >.动态游标

      与静态游标相反,动态游标是可读写的,它会反映出用户对结果集所做的所有修改,包括增删改.特点:读写,消耗资源多,适用于需要频繁更新的情况。

    >.只进游标

      静态游标和动态游标都是可以前后滚动的,而只进游标只能向前滚动游标,不能在结果集中反向移动。一旦过了记录,就无法再次检索。注意:只进游标除了不能向后移动,其他的基本上与动态游标无异,也就是说,它是可读写基础表数据的!

    >.键集驱动游标

      键集驱动游标介于静态游标与动态游标之间.换句话说就是,它同时具备了静态游标与动态游标的部分特点.当打开游标时,该游标中的成员以及行的顺序是固定的,键集在游标打开时也会存储到tempdb中,对非键集列的数据值的更改在用户游标滚动的时候可以看见,在游标打开以后对数据库中插入的行是不可见的,除非关闭重新打开游标.适用于需要对游标进行大量查找和跳跃的情况。

 

  >.游标的基本操作

    遍历游标建议使用 FETCH NEXT方法.

    >.声明游标    
--语法:DECLARE 游标名称 CURSOR FOR + SELECT语句
--例如:
DECLARE cursor_name CURSOR FOR
SELECT column1, column2, ...
FROM table_name
WHERE condition;

举例一:

假设我们有一个名为"employees"的表,包含员工的ID、姓名和薪水字段。我们需要计算员工的总薪水并输出每位员工的姓名和对应的总薪水。

-- 创建一个存储过程
CREATE PROCEDURE calculate_total_salary
AS
BEGIN
    -- 声明游标
    DECLARE employee_cursor CURSOR FOR
    SELECT name, salary
    FROM employees;

    DECLARE @name NVARCHAR(50); -- 声明一个变量用于存储员工姓名
    DECLARE @salary INT; -- 声明一个变量用于存储员工薪水
    DECLARE @total_salary INT = 0; -- 初始化总薪水为0

    -- 打开游标
    OPEN employee_cursor;

    -- 获取数据
    FETCH NEXT FROM employee_cursor INTO @name, @salary; -- 尝试获取第一行数据.
    WHILE @@FETCH_STATUS = 0 -- 当获取到数据时返回0,否则返回-1,这里的循环条件也可以用全局变量 @@cursor_rows 来统计结果集的行数,之后再从1到尾遍历
    BEGIN
        SET @total_salary = @total_salary + @salary; -- 累计总薪水
        PRINT 'Employee ' + @name + ' total salary is ' + CAST(@salary AS NVARCHAR(10)); -- 打印每位员工的姓名和总薪水

        FETCH NEXT FROM employee_cursor INTO @name, @salary; -- 尝试获取下一行数据
    END

    -- 关闭游标
    CLOSE employee_cursor;
    DEALLOCATE employee_cursor;

    PRINT 'Total salary of all employees is ' + CAST(@total_salary AS NVARCHAR(10)); -- 打印所有员工的总薪水
END

举例二:

DECLARE mycurcor SCROLL CURSOR FOR    --注意这里的SCROLL 参数,如果缺省的话,结果栏里将看不到结果
SELECT *
FROM dbo.student
WHERE sex = '';

BEGIN TRY
    OPEN mycurcor;
    DECLARE @i INT,
            @ROWS INT;
    SET @i = 0;    --游标是从0开始的
    SET @ROWS = @@CURSOR_ROWS;   --结果集的行数

    WHILE (@i < @ROWS)   --遍历游标
    BEGIN
        FETCH NEXT FROM mycurcor;   --获取数据
        SET @i += 1;    --变量自增
    END;
END TRY
BEGIN CATCH
    PRINT ERROR_MESSAGE();   --捕获错误
END CATCH;
CLOSE mycurcor;     --关闭游标
DEALLOCATE mycurcor; --释放游标

结果如下:

  

    声明游标时,可以在SELECT语句的末尾加FOR关键字,表示对游标内的数据进行限制,比如

--前面是声明一个游标,SELECT语句后面的For将对数据进行约束
DECLARE employee_cursor CURSOR FOR
SELECT EmployeeID, Name, Department
FROM Employee
ORDER BY EmployeeID
--FOR READ ONLY;   -- 声明游标并限制数据为只读
--FOR update;   -- 更新游标
    >.打开游标
OPEN mycurcor;    --局部游标
OPEN GLOBAL mycurcor;    --GLOBAL 表示指定mycurcor游标为全局游标

如果使用INSENSITIV或者STATIC选项声明了游标,那么 OPEN将创建一个临时表来保存结果集.如果结果集中任意行的大小超过SQL SERVER表的最大行大小,OPEN将失败..另外:游标选项 FOR UPDATE 和 INSENSITIVE 有冲突,不能共存。

-- 声明一个游标并使用 INSENSITIVE 选项
DECLARE employee_cursor INSENSITIVE CURSOR FOR
SELECT EmployeeID, Name, Department
FROM Employee
ORDER BY EmployeeID;

-- 打开游标,创建临时表保存结果集
OPEN employee_cursor;
  >.读取游标中的数据(略,见上面示例)
  >.关闭游标(略,见上面示例)
  >.释放游标(略,见上面示例)

>.使用系统过程查看游标

  >.sp_cursor_list
  >.sp_describe_cursor

 

posted @ 2024-04-30 19:23  一曲轻扬  阅读(28)  评论(0编辑  收藏  举报