您的位置:首页 > 数据库

数据库中游标的使用

2013-01-02 16:00 232 查看
说道游标,我想大家并不陌生。但对于我们大多数初学者来说,就未必用过游标了。下面我就以一个实际例子给大家说一下我们为什么要用游标、什么时候用、怎么用。

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

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



注: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
当我们再次执行假删除学校操作时,你会发现问题完美解决了。结果如下:



到此为止,我相信大家应该清楚为何用游标、什么时候用、怎么用这三个问题了。希望对大家有帮助。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: