数据库中游标的使用

本文探讨了在数据库管理中如何使用触发器来实现特定功能,以School表为例,详细介绍了创建触发器的SQL语句,特别是涉及到的游标在处理数据时的作用。
摘要由CSDN通过智能技术生成
说道游标,我想大家并不陌生。但对于我们大多数初学者来说,就未必用过游标了。下面我就以一个实际例子给大家说一下我们为什么要用游标、什么时候用、怎么用。

实例:某学校有多个班级,而每个班级里有多个学生。现在我们要完成这样一件事,假如有一天,这个学校不存在了,那么属于这个学校的班级也就不存在了,同理,这些班里的学生也就不再属于这个班了。

需求明白了,我们开始建表,表结构如下:

注:IsAvailable字段值为否时标明该条记录不存在。

为了实现上述功能,我们决定用触发器,于是在School表中建立触发器,具体语句如下:

CREATE TRIGGER [dbo].[UpdateClass]
   ON  [dbo].[School]
   AFTER UPDATE
AS
DECLARE
    @schoolID INT,--学校ID
    @isAvailable CHAR(2)--是否可用
BEGIN
    --查询出更新记录的SchoolID和IsAvailable字段值
    SELECT @schoolID=SchoolID, @isAvailable=IsAvailable FROM inserted

    --如果更新的是isAvailable并且更新后的字段值是否
    if (UPDATE(isAvailable) and @isAvailable = '否')
        --标示该学校所有班级不可用(班级表中IsAvailable字段值为否)
        UPDATE Class SET IsAvailable='否' WHERE SchoolID=@schoolID
END

Class表中建立如下触发器
CREATE TRIGGER [dbo].[UpdateStudent]
   ON  [dbo].[Class]
   AFTER UPDATE
AS
DECLARE
    @classID INT,--班级ID
    @isAvailable CHAR(2)--是否可用
BEGIN
    --查询出更新记录的ClassID和IsAvailable字段值
    SELECT @classID=ClassID, @isAvailable=IsAvailable FROM inserted

    --如果更新的是isAvailable并且更新后的字段值是否
    IF (UPDATE(isAvailable) and @isAvailable = '否')
        --更新该班级下的所有学生IsAvailable字段值为否
        UPDATE Student SET IsAvailable='否' WHERE ClassID=@classID
END

Perfect,到此为止,我们的工作貌似要结束了,插入如下数据,测试一下。

执行假删除语句:

UPDATE School SET IsAvailable='否' WHERE SchoolID = 1
结果如下:

分析:从结果可以看出,我们的设计逻辑没有任何问题。两个触发器也被触发了,可结果为何不是我们想要的呢?仔细分析你会发现Class表下的触发器执行了,但是貌似只执行了一次,这就是问题所在之处。那么我们怎么能让每一条更新语句都触发更新触发器呢?此时,咱们今天的主角就要登场了,下面有请“游标”先生闪亮登场。

下面我将直接修改School表下的触发器,里面将用到游标,并附有详细的注释,相信你会看懂的。

School表下修改后的触发器代码:
ALTER TRIGGER [dbo].[UpdateClass]
   ON  [dbo].[School]
   AFTER UPDATE
AS
DECLARE
    @schoolID INT,--学校ID
    @ClassID INT,--班级ID
    @isAvailable CHAR(2)--是否可用
BEGIN
    --查询出更新记录的SchoolID和IsAvailable字段值
    SELECT @schoolID=SchoolID, @isAvailable=IsAvailable FROM inserted

    --如果更新的是isAvailable并且更新后的字段值是否
    IF (UPDATE(isAvailable) AND @isAvailable = '否')
        BEGIN
            --声明游标(集合为删除学校下的班级ID)
            DECLARE ClassCursor CURSOR FOR  
            SELECT ClassID FROM Class WHERE SchoolID = @schoolID
            
            --打开游标
            OPEN ClassCursor
            --当游标被打开时,行指针将指向该游标集第1行之前。
            --如果要读取游标集中的第1行数据,必须移动行指针使其指向第1行。
            FETCH NEXT FROM ClassCursor INTO @ClassID   --给变量赋初始值(游标中第一行数据)

            --每执行一个FETCH操作之后,查看一下全局变量@@FETCH_STATUS中的状态值,以此判断FETCH操作是否成功。
            --变量@@FETCH_STATUS有三种状态值:
            --  0  表示成功执行FETCH语句。
            -- -1  表示FETCH语句失败,例如移动行指针使其超出了结果集。
            -- -2  表示被提取的行不存在。
            WHILE @@FETCH_STATUS=0 --语句执行成功
                BEGIN
                    --标识该学校所有班级不可用(班级表中IsAvailable字段值为否)
                    UPDATE Class SET IsAvailable='否' WHERE ClassID=@ClassID

                    --读取游标中下一条数据,并赋值给@ClassID
                    FETCH NEXT FROM ClassCursor INTO @ClassID
                END

            --关闭并释放游标
            CLOSE ClassCursor  
            DEALLOCATE ClassCursor
        END
END
当我们再次执行 删除学校操作时,你会发现问题完美解决了。结果如下:


到此为止,我相信大家应该清楚为何用游标、什么时候用、怎么用这三个问题了。希望对大家有帮助。

  • 7
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值