【问题标题】:How to use cursor with parameters in SQL Server 2005?如何在 SQL Server 2005 中使用带参数的游标?
【发布时间】:2012-05-05 17:53:59
【问题描述】:

我正在使用的光标是...

Create Proc GetExamResults (@Course_Id varchar(100), @Semester varchar(10))
as
begin
    declare @subjname varchar(100)  
    declare @subjects varchar(7000)  
    declare @subjectsselection varchar(7000)  
    declare @SumSelection varchar(7000)  
    declare @NoOfSubjects int
    set @NoOfSubjects = 0

    set @subjects = ''  
    set @subjectsselection = '' 
    set @SumSelection = ''

    DECLARE subject_cursor CURSOR  
    FOR SELECT distinct Subject_Name FROM Exam_Result where course_id = @Course_Id And Semester = @Semester 

    OPEN subject_cursor  

    FETCH NEXT FROM subject_cursor  
    INTO @subjname  

    WHILE @@FETCH_STATUS = 0  
    BEGIN  
        set @subjects = @subjects + '[' + @subjname + '],'  
        set @subjectsselection = @subjectsselection + 'Sum(Isnull([' + @subjname + '],0)) As [' + @subjname + '],' 
        set @SumSelection = @SumSelection + 'Sum(Isnull([' + @subjname + '],0))+' 

        set @NoOfSubjects = @NoOfSubjects + 1

        FETCH NEXT FROM subject_cursor  
        INTO @subjname  
    End  
    CLOSE subject_cursor;  
    DEALLOCATE subject_cursor;  

    select @subjects = LEFT(@subjects, LEN(@subjects) - 1)  
    select @subjectsselection = LEFT(@subjectsselection, LEN(@subjectsselection) - 1)  
    select @SumSelection = LEFT(@SumSelection, LEN(@SumSelection) - 1)  

    print @subjects  
    print @subjectsselection  
    print @SumSelection

    declare @query nvarchar(4000)  

    set @query = 'select S.Enroll_Number, pvt.Student_Name, pvt.Course_Id, pvt.Semester, ' + @subjectsselection + ',' 
    set @query = @query + 'Exam_Type,' + @SumSelection + ' As Grand_Total, '
    set @query = @query + '(' + @SumSelection + ')' + '/' + convert(varchar(10),@NoOfSubjects) + ' As Avg'
    set @query = @query + ' From '  
    set @query = @query + '(select Enroll_Number, Student_Name, Course_Id, Semester, Subject_Name, MarksObtained, Exam_Type from Exam_Result ) ps '  
    set @query = @query + ' pivot(sum(MarksObtained) for Subject_Name in (' + @subjects + ')) as pvt'  
    set @query = @query + ' inner join Stud_Info S on S.Enroll_Number = pvt.Enroll_Number '
    set @query = @query + ' where pvt.Course_Id = ''' + @Course_Id + ''' and pvt.Semester = ''' + @Semester + ''''
    set @query = @query + ' group by S.Enroll_Number, pvt.Student_Name, pvt.Course_Id, pvt.Semester, Exam_Type'
    print @query
    exec sp_executesql @query  
end

这2个表用在游标...

1] Stud_Info

CREATE TABLE Stud_Info
(Enroll_Number       varchar(20) NOT NULL,  
Salutation           varchar(10) NULL,  
First_Name           varchar(20) NULL,  
Middle_Name          varchar(20) NULL,  
Last_Name            varchar(20) NULL,  
Course_Id            varchar(20) NULL,  
Batch                varchar(20) NULL)

INSERT into Stud_Info values(11161,'Mr.','Mack','B','Botha','MECH','Batch1');    
INSERT into Stud_Info values(11162,'Mr.','John','A','Los','CIVIL','Batch2');    
INSERT into Stud_Info values(11163,'Ms.','Merry','F','Dsuza','ELCT','Batch1');    
INSERT into Stud_Info values(11164,'Mr.','Pow','B','Janero','MECH','Batch2');    
INSERT into Stud_Info values(11165,'Mr.','Martin','J','Smith','MECH','Batch1');    

2] 考试结果

CREATE TABLE Exam_Result
(Result_Id               numeric(18, 0) IDENTITY(1,1) NOT NULL,  
Enroll_Number            varchar(50) NULL,  
Student_Name             varchar(100) NULL,  
Course_Id                varchar(50) NULL,  
Semester                 varchar(50) NULL,  
Subject_Id               varchar(50) NULL,  
Subject_Name             varchar(50) NULL,  
MarksObtained            int NULL,  
Exam_Type                varchar(50) NULL)

INSERT into Exam_Result values(11161,'Mack','MECH',1,'MT','Maths',25,'Internal1');  
INSERT into Exam_Result values(11161,'Mack','MECH',1,'EN','English',22,'Internal1');  
INSERT into Exam_Result values(11161,'Mack','MECH',1,'SC','Science',20,'Internal1');  
INSERT into Exam_Result values(11161,'MACK','MECH',1,'MT','Maths',21,'Internal2');  
INSERT into Exam_Result values(11161,'Mack','MECH',1,'EN','English',24,'Internal2');  
INSERT into Exam_Result values(11161,'Mack','MECH',1,'SC','Science',22,'Internal2');  

这里我用 2 个参数传递它,假设我传递 GetExamResults 'MECH','2'

然后结果就像...

Enroll_Number  Student_Name Course_Id   Semester  Maths    English    Science    **Exam_Type**    total      avg

11161          Mack          MECH         1         25        22          20      **Internal1**      67        total/all sub
11161          Mack          MECH         1         21        24          22      **Internal2**      67        total/all sub

但我想用Exam_Type 跟踪(通过为 Exam_type 添加第三个参数)...并寻找类似.....

当用户执行GetExamResults 'MECH','1','Internal1' 时,结果应该像...

Enroll_Number  Student_Name Course_Id   Semester  Maths    English    Science    **Exam_Type**    total      avg

    11161          Mack          MECH         1         25        22          20      **Internal1**      67        total/all sub

当用户执行GetExamResults 'MECH','1','Internal2' 时,结果应该像...

11161          Mack          MECH         1         21        24          22      **Internal2**      67        total/all sub

【问题讨论】:

    标签: sql-server-2005 stored-procedures parameters cursor error-correction


    【解决方案1】:

    这里。我添加了一个可选参数@Exam_Type。如果不指定值或设置为 null,则过程将返回所有行。 光标定义更改为包括 LOCAL 和 FAST_FORWARD 以加快执行速度。 And (@Exam_Type is null OR @Exam_Type = Exam_Type) 添加到按@Exam_Type 的值过滤exam_results;如果为 null,则不进行过滤。如果@Exam_Type 不为空,则将相同的过滤器添加到(select Enroll_Number, Student_Name, 动态sql 行。

    ALTER Proc GetExamResults (@Course_Id varchar(100), @Semester varchar(10), @Exam_Type varchar(50) = null)
    as
    begin
        declare @subjname varchar(100)  
        declare @subjects varchar(7000)  
        declare @subjectsselection varchar(7000)  
        declare @SumSelection varchar(7000)  
        declare @NoOfSubjects int
        set @NoOfSubjects = 0
    
        set @subjects = ''  
        set @subjectsselection = '' 
        set @SumSelection = ''
    
        DECLARE subject_cursor CURSOR LOCAL FAST_FORWARD
        FOR SELECT distinct Subject_Name FROM Exam_Result where course_id = @Course_Id And Semester = @Semester And (@Exam_Type is null OR @Exam_Type = Exam_Type)
    
        OPEN subject_cursor  
    
        FETCH NEXT FROM subject_cursor  
        INTO @subjname  
    
        WHILE @@FETCH_STATUS = 0  
        BEGIN  
            set @subjects = @subjects + '[' + @subjname + '],'  
            set @subjectsselection = @subjectsselection + 'Sum(Isnull([' + @subjname + '],0)) As [' + @subjname + '],' 
            set @SumSelection = @SumSelection + 'Sum(Isnull([' + @subjname + '],0))+' 
    
            set @NoOfSubjects = @NoOfSubjects + 1
    
            FETCH NEXT FROM subject_cursor  
            INTO @subjname  
        End  
        CLOSE subject_cursor;  
        DEALLOCATE subject_cursor;  
    
        select @subjects = LEFT(@subjects, LEN(@subjects) - 1)  
        select @subjectsselection = LEFT(@subjectsselection, LEN(@subjectsselection) - 1)  
        select @SumSelection = LEFT(@SumSelection, LEN(@SumSelection) - 1)  
    
        print @subjects  
        print @subjectsselection  
        print @SumSelection
    
        declare @query nvarchar(4000)  
    
        set @query = 'select S.Enroll_Number, pvt.Student_Name, pvt.Course_Id, pvt.Semester, ' + @subjectsselection + ',' 
        set @query = @query + 'Exam_Type,' + @SumSelection + ' As Grand_Total, '
        set @query = @query + '(' + @SumSelection + ')' + '/' + convert(varchar(10),@NoOfSubjects) + ' As Avg'
        set @query = @query + ' From '  
        set @query = @query + '(select Enroll_Number, Student_Name, Course_Id, Semester, Subject_Name, MarksObtained, Exam_Type from Exam_Result ' + (case when @Exam_Type is null then '' else ' Where Exam_Type =''' + @Exam_Type + '''' end) + ' ) ps '  
        set @query = @query + ' pivot(sum(MarksObtained) for Subject_Name in (' + @subjects + ')) as pvt'  
        set @query = @query + ' inner join Stud_Info S on S.Enroll_Number = pvt.Enroll_Number '
        set @query = @query + ' where pvt.Course_Id = ''' + @Course_Id + ''' and pvt.Semester = ''' + @Semester + ''''
        set @query = @query + ' group by S.Enroll_Number, pvt.Student_Name, pvt.Course_Id, pvt.Semester, Exam_Type'
        print @query
        exec sp_executesql @query  
    end
    

    【讨论】:

    • Nikola Markovinovic - 当我使用 Exam_Type 传递参数时它工作正常,但在不传递第三个参数 Exam_Type 时它会出错......**错误** 类似于 **Msg 201,级别 16,状态 4,过程 ExamResult,第 0 行过程或函数“ExamResult”需要参数“@Exam_Type”,但未提供该参数。 **
    • @mack28 您是否忘记将= null 放入@Exam_type 的参数列表中?我已经测试了两种方法。
    • Nikola Markovinovic - 是的,我忘了添加 (@Exam_Type 为 null 或 @Exam_Type = Exam_Type) 这一行......谢谢......它有效
    猜你喜欢
    • 1970-01-01
    • 2011-09-09
    • 2020-11-27
    • 1970-01-01
    • 1970-01-01
    • 2010-09-17
    • 1970-01-01
    • 2013-02-01
    • 2011-09-01
    相关资源
    最近更新 更多