数据库--游标

一、游标

游标是系统为用户开设的一个数据缓冲区,存放SQL语句的执行结果。

查询结果为多条记录的SELECT语句、CURRENT 形式的 UPDATE DELETE 语句。

步骤为:说明游标、打开游标、推进游标指针并取当前记录、关闭游标。

CURRENT 形式的 UPDATE DELETE 语句:用到 WHERECURRENT OF <游标名>

 

示例:

--1)、利用游标依次查询学生成绩表中大学物理课程的选课记录,并且输出成绩排名

USE JXGL
GO

-- 查询,并用查询结果建立一个游标
DECLAREGrade_cursor CURSOR SCROLL FOR
 SELECT学生ID,成绩
 FROM
学生成绩表,课程设置表 
 WHERE
学生成绩表.课程ID=课程设置表.课程ID

 AND 课程名='大学物理' AND 成绩 IS NOT NULL
 ORDER BY
成绩

OPEN Grade_cursor

DECLARE @SC_sno varchar(12),@SC_gradeINT    --声明主变量,接收游标区数据
PRINT '
大学物理成绩排名'
PRINT '---------
学号--------成绩----------'

FETCH LAST FROM Grade_cursor INTO@SC_sno,@SC_grade
PRINT '
第一名:  '+@SC_sno+'     '+CONVERT(CHAR(5),@SC_grade)

FETCH RELATIVE -1 FROM Grade_cursorINTO @SC_sno,@SC_grade
PRINT '
第二名:  '+@SC_sno+'     '+CONVERT(CHAR(5),@SC_grade)

FETCH PRIOR FROM Grade_cursor INTO@SC_sno,@SC_grade
PRINT '
第三名:  '+@SC_sno+'     '+CONVERT(CHAR(5),@SC_grade)

FETCH FIRST FROM Grade_cursor INTO @SC_sno,@SC_grade
PRINT '
最低分:  '+@SC_sno+'     '+CONVERT(CHAR(5),@SC_grade)

CLOSE Grade_cursor
DEALLOCATEGrade_cursor
GO

-------------------------------------------------

2)、利用游标逐一查询选修大学英语课程的学生选课记录,如果参加考试且成绩不及格,则删除此选课记录*/

USE JXGL
GO

-- 查询,并用查询结果建立一个游标
DECLARE Grade_cursor CURSOR FOR
 SELECT
学生ID,成绩
 FROM
学生成绩表,课程设置表
 WHERE
学生成绩表.课程ID=课程设置表.课程ID
  
AND 课程名='大学英语'
  
AND 成绩 IS NOT NULL
  
FORUPDATE   

OPEN Grade_cursor

DECLARE @SC_sno varchar(12),@SC_gradeINT

FETCH NEXT FROM Grade_cursor INTO@SC_sno,@SC_grade
WHILE @@FETCH_STATUS = 0         
-------------------------?
BEGIN
 IF @SC_grade<60
     BEGIN 
       DELETEFROM 学生成绩表
          
WHERE CURRENT OFGrade_cursor           ------------------?
       PRINT@SC_sno+'大学英语成绩不及格,删除考试纪录'
     
END
 FETCH NEXT FROM Grade_cursor INTO @SC_sno,@SC_grade
END

CLOSE Grade_cursor
DEALLOCATE Grade_cursor
GO

----
SELECT * INTO
学生成绩表1 FROM 学生成绩表

delete 学生成绩表

insert into 学生成绩表 select * from 学生成绩表1

-----------------------------------------------------------------

3)、--利用游标依次查询学生情况表中不同专业学生的信息(班级,学生ID, 姓名),并输出

USE 教学管理
GO

---声明变量--------
DECLARE @st_id varchar(12),  
--学号
 @st_Spec varchar(20),  
--专业
 @st_class varchar(10), --
班级
 @st_name varchar(10)  
--姓名

--声明游标Spec_cursor------
DECLARE Spec_cursor CURSOR
READ_ONLY       
----------------------?
FOR 
   SELECT distinct 专业
   
FROM 学生情况表
   
order by 专业

--打开游标Spec_cursor------
OPEN Spec_cursor

--Spec_cursor游标中检索行--
FETCH NEXT FROM Spec_cursor INTO @st_Spec     
WHILE @@FETCH_STATUS = 0
BEGIN
 
 --
打印学生名单的表头----
 PRINT @st_Spec+'
学生名单'
 PRINT '--------------------------'
 PRINT '
班级    学号        姓名'
 PRINT '--------------------------'
 
 --
声明游标st_cursor------    --游标中嵌套游标
 DECLARE st_cursor CURSOR FOR 
    
SELECT 班级,学生ID, 姓名
    
FROM 学生情况表
    
WHERE 专业 = @st_Spec
    
ORDER BY 学生ID
 
 OPEN st_cursor
 
 --
st_cursor游标中检索指定系名的记录行--
 FETCH NEXT FROM st_cursor INTO @st_class,@st_id, @st_name
 
 WHILE @@FETCH_STATUS = 0
 BEGIN
  PRINT @st_class+'   
'+@st_id + '    '+@st_name
  FETCH NEXT FROM st_cursor INTO @st_class,@st_id, @st_name
 END
       
        PRINT'--------------------------'
        PRINT' '

 CLOSE st_cursor
 DEALLOCATE st_cursor

 FETCH NEXT FROM Spec_cursor INTO@st_Spec
END

CLOSE Spec_cursor
DEALLOCATE Spec_cursor
GO

--------------------------------------------

 

二、存储过程

存储过程和函数是命名块,被编译后保存在数据库中,可以被反复调用,运行速度较快,使用时只需调用即可。

 

示例:

1)、带有输入参数

为教学管理数据库创建一存储过程proc1,显示指定学生(根据学号id)选择各门课程的成绩

USE JXGL
GO

CREATE PROC proc1      ---创建存储过程
@snum char(10) =NULL    
--参数列表(需指定数据类型);此处初始为空
AS                      
--后为SQL
IF @snum IS NULL 
     
PRINT '请重新执行,你必须提供学号!'
ELSE
IF NOT EXISTS (SELECT * FROM
学生情况表 WHERE 学生ID=@snum)   ---如果输入的学生ID不存在于学生情况表
     
PRINT '请提供正确的学号!'
ELSE
    
SELECT A.学生ID,姓名,课程名,成绩
    
FROM 学生情况表 A, 学生成绩表 B , 课程设置表 C
    
WHERE A.学生ID= B.学生ID
          
and C.课程ID= B.课程ID
          
and B.学生ID= @snum
GO

--执行proc1

  DECLARE @snum char(10)  ---声明主变量
  
SET @snum ='4100205'   --指定主变量的值,即指定的学生
  
EXECUTE proc1@snum      --执行存储过程

------------------------------------------------------------------------
2
)、带有输出参数

为教学管理数据库创建一个带有输出参数(OUTPUT)的存储过程存proc2,显示指定课程的考试成绩在指定分数段的学生,并返回该分数段的学生人数

--1声明创建存储过程
create PROC proc2       

--2、参数列表
@lscorefloat,   --指定分数段的最低分
@hscore float,   
--指定分数段的最高分
@cnum nvarchar(10),   
--课程ID
@STU_COUNT smallint  
OUTPUT       --------------------------代表是输出参数
AS

--3SQL
--显示指定课程的考试成绩在指定分数段的学生(学生ID,姓名,指定课程的成绩)

    SELECT B.学生ID, 姓名, 成绩
    
FROM 学生情况表 A, 学生成绩表 B
    
WHERE A.学生ID= B.学生ID
        
andB.课程ID=@cnum
        
and成绩 BETWEEN @lscore and @hscore
    
ORDER BY 成绩, B.学生ID

--计算该分数段的学生人数; 
SET @STU_COUNT=( SELECT count(distinct D.
学生ID)  
                 
FROM 学生成绩表 D
               
WHERE D.课程ID= @cnum
               
and 成绩 BETWEEN@lscore and @hscore)  
GO

--4、执行proc2,统计并输出指定课程,指定成绩段内的人数
declare @l int,@h int,@kh char(10),@rs int
set @l=60
set @h=80
set @kh='032101'  
--课程ID
exec proc2 @l, @h,@kh ,@rs output
print rtrim(@kh)+'
课程'+convert(char(3),@l)+'-'+convert(char(3),@h)+'分人数:'+convert(char(2),@rs)+''
----------------convert
语句该如何用

------------------------------------------------------

3)、使用游标

为教学管理数据库创建一个带有 OUTPUT 游标参数的存储过程, 统计某课程考试成绩在指定分数段的学生人数,并输出学生成绩单

ALTER PROC proc3
@lscore float,
@hscore float,
@cnum nvarchar(10),
@STU_COUNT int OUTPUT,
@STU_list CURSOR VARYING OUTPUT     
--输出游标参数
AS
SET @STU_COUNT=( SELECT count(distinct
学生ID)
                 
FROM 学生成绩表 
                 
WHERE 课程ID= @cnumand
                      
成绩 BETWEEN@lscore and @hscore)  
SET @STU_list=CURSOR
 FOR
        
SELECTB.学生ID,姓名,成绩
        
FROM学生情况表 A,学生成绩表 B
        
WHEREA.学生ID= B.学生ID
                
and B.课程ID=@cnum
                
and 成绩 BETWEEN@lscore and @hscore
        
ORDERBY 成绩, B.学生ID                         --定义游标@STU_list


OPEN @STU_list       
--打开游标@STU_list

GO
---------

--执行proc3,统计并输出指定课程,指定成绩段内的人数
declare @l int,@h int,@kh char(10),@rs int 
DECLARE  
@STlistCURSOR                     --声明游标类型变量
set @l=60
set @h=80
set @kh='032101'
exec proc3 @l, @h,@kh ,@rs output,@STU_list= @STlist OUTPUT

DECLARE @stnum char(10),@stnamechar(10),@stgrade float    --声明游标中使用的接收变量
print rtrim(@kh)+'
课程'+convert(char(3),@l)+'-'+convert(char(3),@h)+'分人数:'+convert(char(2),@rs)+''
print '--------------------------------'
print '
学号      姓名      成绩         '
print '--------------------------------'
FETCH NEXT FROM @STlist INTO @stnum ,@stname ,@stgrade
WHILE (@@FETCH_STATUS = 0)
      BEGIN
    print@stnum+@stname+convert(char(5),@stgrade)
   FETCH NEXT FROM@STlist INTO @stnum ,@stname ,@stgrade
      END

--CLOSE@STlist        --关闭游标@STCOUNT
--DEALLOCATE @STlist   
--释放游标@STCOUNT

go

 

以下是对应的三个存储过程: 1. 统计离散数学的成绩分布情况 ``` CREATE PROCEDURE `DiscreteMathScoreDistribution`() BEGIN SELECT '90-100' AS 'Score Range', COUNT(*) AS 'Number of Students' FROM student_course WHERE course_id = 'MATH101' AND score >= 90 AND score <= 100 UNION SELECT '80-89', COUNT(*) FROM student_course WHERE course_id = 'MATH101' AND score >= 80 AND score < 90 UNION SELECT '70-79', COUNT(*) FROM student_course WHERE course_id = 'MATH101' AND score >= 70 AND score < 80 UNION SELECT '60-69', COUNT(*) FROM student_course WHERE course_id = 'MATH101' AND score >= 60 AND score < 70 UNION SELECT '0-59', COUNT(*) FROM student_course WHERE course_id = 'MATH101' AND score >= 0 AND score < 60; END ``` 2. 统计任意一门课的平均成绩 ``` CREATE PROCEDURE `CourseAvgScore`(IN courseID VARCHAR(10)) BEGIN SELECT AVG(score) AS 'Average Score' FROM student_course WHERE course_id = courseID; END ``` 3. 将学生选课成绩从百分制改为等级制 ``` CREATE PROCEDURE `ConvertToGradeScore`() BEGIN UPDATE student_course SET score = CASE WHEN score >= 90 THEN 'A' WHEN score >= 80 AND score < 90 THEN 'B' WHEN score >= 70 AND score < 80 THEN 'C' WHEN score >= 60 AND score < 70 THEN 'D' ELSE 'E' END; END ``` 注意事项: - 第一个存储过程中的 course_id = 'MATH101' 需要改为对应需要统计的课程ID - 第二个存储过程中的 IN courseID 可以改为任意需要统计平均成绩的课程ID - 第三个存储过程将原来的分数覆盖为等级,需要谨慎操作,并且要确保该过程只执行一次。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值