数据库中游标的使用
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表中建立如下触发器:
Perfect,到此为止,我们的工作貌似要结束了,插入如下数据,测试一下。
执行假删除语句:
分析:从结果可以看出,我们的设计逻辑没有任何问题。两个触发器也被触发了,可结果为何不是我们想要的呢?仔细分析你会发现Class表下的触发器执行了,但是貌似只执行了一次,这就是问题所在之处。那么我们怎么能让每一条更新语句都触发更新触发器呢?此时,咱们今天的主角就要登场了,下面有请“游标”先生闪亮登场。
下面我将直接修改School表下的触发器,里面将用到游标,并附有详细的注释,相信你会看懂的。
School表下修改后的触发器代码:
到此为止,我相信大家应该清楚为何用游标、什么时候用、怎么用这三个问题了。希望对大家有帮助。
实例:某学校有多个班级,而每个班级里有多个学生。现在我们要完成这样一件事,假如有一天,这个学校不存在了,那么属于这个学校的班级也就不存在了,同理,这些班里的学生也就不再属于这个班了。
需求明白了,我们开始建表,表结构如下:
注: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当我们再次执行假删除学校操作时,你会发现问题完美解决了。结果如下:
到此为止,我相信大家应该清楚为何用游标、什么时候用、怎么用这三个问题了。希望对大家有帮助。
相关文章推荐
- 关于sql server动态获取数据库下所有表以及游标的简单使用
- mysql 数据库 简单存储过程游标使用
- 关于在存储过程中使用游标操作数据库
- 数据库游标的使用
- 数据库中游标的使用
- 使用游标删除数据库表
- Oracle 10g数据库游标的使用学习三(实践)
- 数据库游标的使用
- 数据库中游标的使用
- 数据库中游标的使用
- postgresql数据库的游标使用例子说明
- 数据库中游标的使用.....用于循环
- Oracle 10g数据库游标的使用学习二
- 数据库游标使用mysql(全表操作)
- 使用游标批量更新/填充数据库(The Using of Cursor)
- oracle pl/sql之使用游标变量更新数据库
- 数据库中游标的使用.....用于循环
- 数据库游标使用大全
- 【SQL】使用游标进行不同数据库的…
- 使用游标批量更新/填充数据库(The Using of Cursor)