简体   繁体   English

在带有循环的 Microsoft SQL 服务器中使用游标

[英]Using cursors in Microsoft SQL Server with a loop

Problem:问题:

Write a script that determines if too few students (less than five) or too many students (greater than 10) are enrolled in each course.编写一个脚本,确定每门课程注册的学生是否太少(少于 5 人)或太多的学生(超过 10 人)。 To do that, you can use a cursor.为此,您可以使用 cursor。 This cursor should use a SELECT statement that gets the CourseID and the count of students for each course from the StudentCourses table.此 cursor 应使用SELECT语句,该语句从StudentCourses表中获取每门课程的CourseID和学生人数。

When you loop through the rows in the cursor, the script should display a message like this if there are too few students enrolled in a course:当您遍历 cursor 中的行时,如果参加课程的学生太少,脚本应显示如下消息:

"Too few students enrolled in course x" where x is the course ID. “参加课程 x 的学生太少”,其中 x 是课程 ID。 The script should display a similar message if there are too many students enrolled in a course.如果课程中注册的学生过多,脚本应该会显示类似的消息。

My code so far:到目前为止我的代码:

DECLARE Students_Cursor CURSOR FOR 
    SELECT c.CourseID, COUNT(sc.StudentID) 
    FROM Courses c 
    JOIN StudentCourses sc ON c.CourseID = sc.CourseID
    WHERE COUNT(sc.StudentID) < 5  OR COUNT(sc.StudentID) > 10

OPEN Student_Cursor;

FETCH NEXT FROM Students_Cursor

WHILE @@FETCH_STATUS <> -1
BEGIN
    IF 

Using a CURSOR is usually slower than better alternate options.使用 CURSOR 通常比更好的替代选项慢。 That being said, the first thing you would need to work on is getting the SELECT statement working.话虽如此,您需要做的第一件事就是让 SELECT 语句正常工作。 I don't think it will work as you have it.我不认为它会像你一样工作。 If you are using a COUNT, you are aggregating.如果您使用的是 COUNT,则表示您正在聚合。 If you want to filter the results by the aggregate, you can't do that with the WHERE clause.如果要按聚合过滤结果,则不能使用 WHERE 子句来执行此操作。 Instead you would need to move it into a HAVING clause.相反,您需要将其移动到 HAVING 子句中。 Also, since you are selecting more than the aggregate counts, you need to GROUP BY the CourseID.此外,由于您选择的数量超过了总数量,因此您需要按 CourseID 进行分组。 To continue this route, you would have a SELECT like:要继续这条路线,您将拥有 SELECT ,例如:

SELECT c.CourseID, COUNT(sc.StudentID) FROM Courses c JOIN StudentCourses sc
ON c.CourseID= sc.CourseID
GROUP BY c.CourseID
HAVING COUNT(sc.StudentID) < 5  OR COUNT(sc.StudentID) > 10;

Not that it is a bad idea to limit the number of rows you are going to run through in the CURSOR, but if you are going to be checking for the number of students as part of the CURSOR, maybe they are looking for you to do the logic in the CURSOR itself.并不是说限制您将在 CURSOR 中运行的行数是一个坏主意,但是如果您要检查学生人数作为 CURSOR 的一部分,也许他们正在寻找您做CURSOR 本身的逻辑。 You could just eliminate the HAVING clause and go through all of the rows in the CURSOR instead.您可以通过 CURSOR 中的所有行来消除 HAVING 子句和 go 。

Once you get the SELECT straightened out, and you FETCH from the CURSOR, you want to pull the items you SELECT into variables you can then use to generate your messages.一旦你把 SELECT 理顺,并且你从 CURSOR 获取,你想把你 SELECT 的项目拉到变量中,然后你可以使用它来生成你的消息。 Therefore, you want to DECLARE them earlier, and then pull the CURSOR values into them.因此,您想提前声明它们,然后将 CURSOR 值拉入其中。 Something like就像是

FETCH NEXT FROM Students_Cursor INTO @CourseID, @StudentCount;
WHILE @@FETCH_STATUS <> -1

Then you can do your IF/THEN conditions on the @StudentCount, and use @CourseID in the message.然后您可以在@StudentCount 上执行您的IF/THEN 条件,并在消息中使用@CourseID。 Just make sure that after that, you FETCH NEXT FROM into the variables again inside of the BEGIN/END block, then of course CLOSE and DEALLOCATE the CURSOR.只需确保在那之后,您在 BEGIN/END 块内再次将 NEXT FROM 提取到变量中,然后当然关闭并释放 CURSOR。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM