需要替代游标来进行sql查询。目前需要太长时间

时间:2012-08-31 16:05:24

标签: sql stored-procedures cursor

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 个答案:

答案 0 :(得分:1)

这里最好的办法是将spi_GBCalcStudentAverage程序更改为表值UDF,如果可以的话。这将允许您将其包含在一个基于集合的查询中,该查询将替换您的光标。

除非你这样做,否则你将无法摆脱光标,因为你无法在基于集合的查询中调用存储过程。

答案 1 :(得分:0)

如果你必须运行一个无法按行更改的存储过程,那么你就是SOL。你被光标困住了。

根据您填充的行数,您可能需要考虑将临时表#TempTable更改为表变量@TempTable。这可以提高性能,但是有一个阈值表大小,性能突然变为表变量。

答案 2 :(得分:0)

您要么获得正确重构所需的权利,要么以糟糕的表现为生,并告诉客户为何无法改善性能。

您可以通过两种方式进行重构:

重写sp以接受一组数据作为输入,通过可变的逗号分隔列表或通过使用tableinput变量(较新版本的SQl服务器)

或者创建一个tablevalued函数。如果他们可以给你sp的代码,你可以创建表值函数来使用set theroy而不是row-by-agonizing-row调用proc。他们更愿意让你创建一个新对象,而不是改变应用程序的其他部分正在使用的对象。

然而,所有这一切的真正关键在于,如果没有创建或更改需要更改的内容以解决问题所需的权限,那么期望您创建解决方案是绝对不可接受的。客户做了什么让你瘫痪。就好像你想让机械师修理你的车一样,但你拒绝给他启动发动机的钥匙。在给你车钥匙之前,你不能完成专业工作。