以下存储过程是鄙人前几日发问的那个在线招聘考试系统上用到的存储过程之一,且看该存储过程的书写:
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
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
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次的访问,其中一次查询,一次更新
比之第一个存储过程,优化之后的存储过程减少了三次的对数据更新的次数。
对于为什么减少了数据表的更新次数,请大家看存储过程。在此鄙人就不啰嗦了。