CREATE TABLE #TempTable (stuID int, courseID int,outputvalue decimal(9,5))
DECLARE @parm1 int, @parm2 int, @parm3 int, @parm4 int, @parm5 varchar(10)
, @parm6 datetime, @parm7 datetime, @parm8 datetime, @parm9 varchar(5),@parm10 char(1),@parm11 char(1)
DECLARE gradeCursor CURSOR FAST_FORWARD FOR
SELECT
3968585,
reg.building,
schd_ms.[section_key],
schd_ms_session.course_session,
CONVERT(nvarchar,reg.student_id),
'2012-07-01',
'2013-06-30',
REPLACE(convert(varchar, getdate(), 102),'.','-'),
'%',
'N',
'Y'
FROM test.dbo.reg
INNER JOIN schd_stu_course on schd_stu_course.student_id = reg.student_id
INNER JOIN schd_ms on schd_stu_course.section_key = schd_ms.section_key
JOIN schd_ms_session on schd_ms_session.section_key = schd_ms.section_key
where schd_ms.school_year = '2013'
OPEN gradeCursor
FETCH NEXT FROM gradeCursor INTO
@parm1,@parm2,@parm3,@parm4,@parm5,@parm6,@parm7,@parm8,@parm9,@parm10,@parm11
WHILE @@FETCH_STATUS = 0
BEGIN
DECLARE @odecStudentAverage decimal(9,5)
EXECUTE [Test_Live].[dbo].[spi_GBCalcStudentAverage] @Parm1, @Parm2, @Parm3, @Parm4, @Parm5, @Parm6, @Parm7, @Parm8, @Parm9,@Parm10, @Parm11, @odecStudentAverage output
INSERT INTO #TempTable (stuID, courseID,outputvalue)
Select @Parm5, @Parm3, @odecStudentAverage
FETCH NEXT FROM gradeCursor INTO
@parm1,@parm2,@parm3,@parm4,@parm5,@parm6,@parm7,@parm8,@parm9,@parm10,@parm11
END
CLOSE gradeCursor
DEALLOCATE gradeCursor
SELECT
reg.student_id,
reg.building,
schd_ms.[course],
schd_ms.[section_key],
schd_ms.[description],
'',
'',
schd_ms_session.CREDIT,
schd_ms_session.START_PERIOD,
schd_ms_session.END_PERIOD,
schd_ms_session.ROOM_ID,
schd_ms_session.PRIMARY_STAFF_ID,
schd_ms_session.course_session,
#TempTable .outputvalue
FROM test_live.dbo.reg
INNER JOIN schd_stu_course on schd_stu_course.student_id = reg.student_id
INNER JOIN schd_ms on schd_stu_course.section_key = schd_ms.section_key
JOIN schd_ms_session on schd_ms_session.section_key = schd_ms.section_key
JOIN #TempTable on reg.student_id = #TempTable .stuID AND schd_ms.[section_key] = #TempTable .courseID
where schd_ms.school_year = '2013'
3 回答
如果可以的话,您最好的选择是将您的spi_GBCalcStudentAverage
过程更改为表值 UDF。这将允许您将其包含在将替换您的光标的基于集合的查询中。
除非您这样做,否则您将无法摆脱游标,因为您无法在基于集合的查询中调用存储过程。
您要么需要获得正确重构所需的权利,要么忍受糟糕的性能并告诉客户为什么无法提高性能。
您可以通过两种方式进行重构:
重写 sp 以通过带有逗号分隔列表的变量或通过使用 tableinput 变量(较新版本的 SQl 服务器)接受一组数据作为输入
或者创建一个表值函数。如果他们可以为您提供 sp 代码,您可以创建表值函数以使用 set theroy 而不是逐行调用 proc。他们可能更愿意让您创建一个新对象,而不是更改应用程序的其他部分正在使用的对象。
然而,所有这一切的真正关键在于,期望您创建解决方案而没有创建或更改需要更改以解决问题的权利是绝对不能接受的。客户的所作所为使您瘫痪。就好像您希望机械师修理您的汽车,但您拒绝给他启动引擎的钥匙。在你拿到车钥匙之前,你不能从事专业的工作。
如果您必须运行一个无法在每行基础上更改的存储过程,那么您几乎就是 SOL。你被光标卡住了。
根据您填充的行数,您可能需要考虑将临时表#TempTable
更改为表变量@TempTable
。这可以提高性能,但是存在一个阈值表大小,在该阈值表大小上,性能会突然因表变量而下降。