以下存储过程是鄙人前几日发问的那个在线招聘考试系统上用到的存储过程之一,且看该存储过程的书写:

 1/*
 2---------------------------------------------------------------------------------
 3--存储过程名:pro_stuAnswerTime
 4--输入参数:
 5  --@RecruID 招聘ID
 6  --@TestID  考试ID
 7  --@PaperID 试卷ID
 8  --@StuID   考生ID
 9    @SpentHours 剩余小时,
10    @SpentMinutes 剩余分钟,
11    @SpentSeconds 剩余秒
12--输出参数:
13  --@IsPassedTime 是否超时
14------------------
15------------------
16--用途:
17--考生考试用时处理
18
19---------------------------------------------------------------------------------
20*/

21
22CREATE PROCEDURE dbo.pro_stuAnswerTime 
23    @RecruID int,
24    @TestID int,
25    @PaperID int,
26    @StuID int,
27    @SpentHours int,
28    @SpentMinutes int,
29    @SpentSeconds int
30AS
31    --更新考生用时表
32    if (select count(*from Tb_StuTestRecord where  RecruID=@RecruID and TestID=@TestID and PaperID=@PaperID and StuID=@StuID=0
33        begin 
34            insert into Tb_StuTestRecord(RecruID,TestID,PaperID,StuID,SpentHours,SpentMinutes,SpentSeconds) values(@RecruID,@TestID,@PaperID,@StuID,@SpentHours,@SpentMinutes,@SpentSeconds)
35        end
36    else
37        begin
38            update Tb_StuTestRecord set SpentHours=SpentHours+@SpentHours,SpentMinutes=SpentMinutes+@SpentMinutes,SpentSeconds=SpentSeconds+@SpentSeconds 
39            where RecruID=@RecruID and TestID=@TestID and PaperID=@PaperID and StuID=@StuID;
40            
41            
42            
43        --以下代码用来进行 分 秒 的转换
44        --即60秒 换做一分,60分换做一秒
45         declare @min int;
46         declare @seconds int;
47         
48         --从表中查出相应的秒来判断
49         select @seconds=SpentSeconds from Tb_StuTestRecord
50         where  RecruID=@RecruID and TestID=@TestID and PaperID=@PaperID and StuID=@StuID
51         
52         --秒大于60
53         if @seconds>=60 
54            begin
55                    update Tb_StuTestRecord set SpentMinutes=SpentMinutes+1,SpentSeconds=0
56                where RecruID=@RecruID and TestID=@TestID and PaperID=@PaperID and StuID=@StuID;
57            end
58        
59         --从表中查出相应的分来判断
60         select @min=SpentMinutes from Tb_StuTestRecord
61         where  RecruID=@RecruID and TestID=@TestID and PaperID=@PaperID and StuID=@StuID
62         --分钟大于60
63         if @min>=60
64            begin 
65                update Tb_StuTestRecord set SpentHours=SpentHours + 1,SpentMinutes=0 where RecruID=@RecruID and TestID=@TestID and PaperID=@PaperID and StuID=@StuID;
66            end
67        
68    end
69

且看一下该存储过程对数据表访问了几次:
1.第32行,先从表中查出了一条记录,查询一次
2.如果走分支一的话,则只对表进行一次更新
3.如果走分支二,则会出现如下情况:
    3.1 更新一次表
    3.2 如果秒大于60,则又更新一次表
    3.3 如果分大于60,则第三次更新表

综上,对数据表的访问的最大次数可能达到1+1+1+1=4次,其中一次查询、三次更新,那么这样的效率肯定是比较低的。

针对以上存储过程,采取了网友们的建议,对以上存储过程进行了如下优化:
 1
 2declare @hour int;
 3declare @min int;
 4declare @sec int;
 5declare @affectedrowscount int;--表示是否更新的学生考试表(如果其值为0,则说明应该向该表中插入记录)
 6
 7--从表中查出考生已用时、分、秒
 8select @hour=SpentHours,@min=SpentMinutes,@sec=SpentSeconds from Tb_StuTestRecord
 9         where  RecruID=@RecruID and TestID=@TestID and PaperID=@PaperID and StuID=@StuID
10        
11        --声明更新之后应该是的时分秒
12        declare @okhour int;
13        declare @okmin int;
14        declare @oksec int;
15        
16        set @okhour=@hour+@SpentHours;
17        set @okmin = @min + @SpentMinutes;
18        set @oksec= @sec + @SpentSeconds;
19
20    if @oksec>=60
21    begin 
22        set @okmin = @okmin +1;
23        set @oksec = @oksec -60;
24    end
25
26    if @okmin>=60
27    begin
28        set @okhour = @okhour +1;
29        set @okmin = @okmin  - 60;
30    end
31    
32        update Tb_StuTestRecord set SpentHours=@okhour,SpentMinutes=@okmin,SpentSeconds=@oksec where RecruID=@RecruID and TestID=@TestID and PaperID=@PaperID and StuID=@StuID;
33        
34        --取出受影响的行数,作为下面的一个判断条件
35         set @affectedrowscount = @@rowcount;
36
37--如果更新时影响的行数为0,则说明表中并无该记录,此时应
38    if(@affectedrowscount = 0)
39        begin 
40                insert into Tb_StuTestRecord(RecruID,TestID,PaperID,StuID,SpentHours,SpentMinutes,SpentSeconds) values(@RecruID,@TestID,@PaperID,@StuID,@SpentHours,@SpentMinutes,@SpentSeconds)
41        end
42GO

且看优化后的存储过程:
1.第8 行从数据库中查询出相应的记录,并赋值给三个相应的变量
2.更新一次表
3.如果更新影响的行数为0,则向数据库中插入记录(此分支在考生答题的整个过程中只可能走一次)

由此:整个存储过程对该表进行了相当于2次的访问,其中一次查询,一次更新

比之第一个存储过程,优化之后的存储过程减少了三次的对数据更新的次数。
对于为什么减少了数据表的更新次数,请大家看存储过程。在此鄙人就不啰嗦了。
posted on 2007-10-26 18:50  是谁啊?  阅读(1140)  评论(0编辑  收藏  举报