如何检查存储过程中两个 SELECT 语句的输出是不是相等、大于或小于?

Posted

技术标签:

【中文标题】如何检查存储过程中两个 SELECT 语句的输出是不是相等、大于或小于?【英文标题】:How to check if the output of two SELECT statements are equal, greater than, or less than in a stored procedure?如何检查存储过程中两个 SELECT 语句的输出是否相等、大于或小于? 【发布时间】:2016-08-17 23:14:27 【问题描述】:

为了做一个注册系统,我做了一个数据库来存储班级的学生和教授。但是,我正在尝试创建一个存储过程来检查“Sections”表中的classSize 属性是否大于或等于classSizeCap 属性。但是,我遇到了一个问题。 PostgreSQL 无法识别我的 CASEIF 语句。我应该如何解决这个问题?

-- 将显示学生需要覆盖哪个课程 -- 创建或替换函数 startOverrides(REFCURSOR) RETURNS refcursor AS $$ 宣布 class_size INT := (PERFORM Sections.classSize 从部分 INNER JOIN Enrollment ON Enrollment.courseID = Sections.courseID WHERE Enrollment.sectionNumber = Sections.sectionNumber); class_members INT := (PERFORM students_enrolled.courseName, COUNT(*) FROM students_enrolled GROUP BY students_enrolled.courseName, COUNT(*)); 覆盖 REFCURSOR := $1; 开始 OPEN 覆盖 FOR 当 class_size >= class_members 时的情况 然后选择 students_enrolled.fname、students_enrolled.lname、students_enrolled.courseName、SUM(Sections.classSizeCap - Sections.classSize) AS 覆盖 FROM students_enrolled 在 Sections.courseID = students_enrolled.courseID 上的 INNER JOIN 部分 AND Sections.sectionNumber = students_enrolled.sectionNumber GROUP BY students_enrolled.fname、students_enrolled.lname、students_enrolled.courseName、SUM(Sections.classSizeCap - Sections.classSize) 万一; 返回覆盖; 结尾 $$ 语言 plpgsql; 选择 student_enrolled('覆盖'); FETCH ALL FROM 覆盖;

我的错误:

错误:“CASE”处或附近的语法错误 第 8 行:CASE WHEN(选择 Sections.classSize ^ ********** 错误 ********** 错误:“CASE”处或附近的语法错误 SQL 状态:42601 人物:151

这是我主要使用的视图:

创建或替换视图 students_enrolled AS 选择 People.fname、People.lname、Courses.courseID、Courses.courseName、Students.creditsEarned 从注册 INNER JOIN People ON Enrollment.studentID = People.pid INNER JOIN Students ON Enrollment.studentID = Students.studentID INNER JOIN Courses ON Enrollment.courseID = Courses.courseID 按 People.fname、People.lname、Courses.courseID、Courses.courseName、Students.creditsEarned 分组;

这是我的数据库的快照:

-- 在没有课程实例的情况下举办特定课程 -- 创建表课程( courseID SERIAL UNIQUE NOT NULL, 部门文本不为空, courseNumber VARCHAR(10) NOT NULL, courseName TEXT UNIQUE NOT NULL, 积分 INT NOT NULL, 主键(课程 ID) ); -- 提供特定课程 -- CREATE TABLE ClassesAvailable ( courseID INT NOT NULL, 年份 INT NOT NULL, 术语文本不为空, 检查(term = 'Fall' OR term = 'Winter' OR term = 'Spring' OR term = 'Summer'), 主键(课程 ID、年份、学期) ); -- 人超型 -- 创建表人( pid SERIAL UNIQUE NOT NULL, fname 文本不为空, lname TEXT NOT NULL, 主键(pid) ); -- 拥有不同的教授在学校任教 -- -- 人的亚型 -- 创建表教授( 教授ID INT UNIQUE NOT NULL, 状态文本不为空, 检查(状态='全职'或状态='兼职'), 主键(教授 ID), 外键(professorID) 参考人物(pid) ); -- 持有取决于年份和期限的类的具体实例 -- 创建表部分( courseID INT NOT NULL, 年份 INT NOT NULL, 术语文本不为空, sectionNumber INT NOT NULL, 开始日期日期不为空, endDate 日期不为空, crn INT 非空, classSize INT NOT NULL, classSizecap INT NOT NULL, 检查(term = 'Fall' OR term = 'Winter' OR term = 'Spring' OR term = 'Summer'), 主键(courseID,年份,学期,sectionNumber), FOREIGN KEY(courseID, year, term) REFERENCES ClassesAvailable(courseID, year, term) ); -- 举办班级活动 -- -- 一个班级可能有不同的日子 -- ——他们见面了,所以这允许一定的—— -- 部分有几天没有冲突 -- 创建表类事件( 教授ID INT NOT NULL, courseID INT NOT NULL, 年份 INT NOT NULL, 术语文本不为空, sectionNumber INT NOT NULL, 日文本, 开始时间时间, endTime 时间, 位置文本, 校园文, 检查(day = 'Monday' OR day = 'Tuesday' OR day = 'Wednesday' OR day = 'Thursday' OR day = 'Friday' OR day = 'Saturday' OR day = 'Sunday' OR day IS NULL), 检查(term = 'Fall' OR term = 'Winter' OR term = 'Spring' OR term = 'Summer'), 检查(校园='主要'或校园='在线'或校园='意大利'), 主键(professorID, courseID, year, term, sectionNumber, day, startTime, endTime), FOREIGN KEY(professorID) REFERENCES 教授(professorID), FOREIGN KEY(courseID, year, term, sectionNumber) 参考 Sections(courseID, year, term, sectionNumber) ); -- 生成先决条件 -- 创建表先决条件( courseID INT NOT NULL, 年份 INT NOT NULL, 术语文本不为空, prereqID INT NOT NULL, 检查(term = 'Fall' OR term = 'Winter' OR term = 'Spring' OR term = 'Summer'), 主键(courseID、年份、学期、prereqID)、 FOREIGN KEY(courseID, year, term) REFERENCES ClassesAvailable(courseID, year, term), 外键(prereqID) 参考课程(courseID) ); -- 持有将要上课的学生 -- -- 人的亚型 -- 创建表学生( studentID INT UNIQUE NOT NULL, gradYear INT NOT NULL, creditsEarned INT NOT NULL, 主键(学生 ID), 外键(studentID) 参考人物(pid) ); -- 拥有学生(可能还有教授)的一流记录 -- 创建表注册 ( 学生ID INT NOT NULL, courseID INT NOT NULL, 年份 INT NOT NULL, 术语文本不为空, sectionNumber INT NOT NULL, 检查(term = 'Fall' OR term = 'Winter' OR term = 'Spring' OR term = 'Summer'), 主键(studentID, courseID, year, term, sectionNumber), 外键(studentID)参考学生(studentID), FOREIGN KEY(courseID, year, term, sectionNumber) 参考 Sections(courseID, year, term, sectionNumber) ); -- 拥有可以在学院/大学获得的不同学位 -- 创建表度数( degreeID SERIAL UNIQUE NOT NULL, 学位名称文本不为空, degreeType TEXT NOT NULL, degDepartment VARCHAR(4) 非空, 检查(degreeType = 'Major' OR degreeType = 'Minor' OR degreeType = 'Masters'), 主键(学位 ID) ); -- 开设学位课程 -- 创建表 DegreeReq ( degreeID INT REFERENCES Degrees(degreeID) NOT NULL, courseID INT REFERENCES Courses(courseID) NOT NULL, 主键(学位 ID,课程 ID) ); -- 持有特定学生的学位 -- -- 例如:一个学生可以有一个主修和一个辅修 -- -- 这样他/她就可以单独存放它们 -- 创建表学位实例( degreeID INT REFERENCES Degrees(degreeID) UNIQUE NOT NULL, studentID INT REFERENCES Students(studentID) UNIQUE NOT NULL, 开始日期日期不为空, endDate 日期不为空, creditsRequired INT NOT NULL, 主键(学位ID,学生ID) ); -- 持有我教授统计的所有费率 -- 创建表评级 ( 教授ID INT UNIQUE NOT NULL, rmpID BIGINT UNIQUE NOT NULL, avgRating FLOAT NOT NULL, avgHelpfulness FLOAT NOT NULL, avgClarity FLOAT NOT NULL, avgEasiness FLOAT NOT NULL, 主键(professorID, rmpID), FOREIGN KEY(professorID) REFERENCES 教授(professorID) ); -- 保持学生的课堂记录 -- 创建表 ClassRecord ( 学生ID INT NOT NULL, courseID INT NOT NULL, 年份 INT NOT NULL, 术语文本不为空, 等级文本不为空, 检查(等级='A'或等级='A-'或等级='B+'或等级='B'​​或等级='B-'或等级='C+'或等级='C'或等级='C -' 或等级 = 'D+' 或等级 = 'D' 或等级 = 'D-' 或等级 = 'F' 或等级 = 'P'), 主键(学生 ID、课程 ID、年份、学期、年级)、 FOREIGN KEY(courseID, year, term) REFERENCES ClassesAvailable(courseID, year, term), 外键(studentID) 参考资料 学生(studentID) );

有什么建议吗?

【问题讨论】:

【参考方案1】:

您可以使用INTO 将结果分配给变量。

这样您就可以将两个 select 语句都分配给一个变量,并在 CASE 语句中比较它们。

-- WILL SHOW WHAT STUDENTS NEED OVERRIDES FOR WHICH CLASS --
CREATE OR REPLACE FUNCTION startOverrides(REFCURSOR) RETURNS refcursor AS
$$
DECLARE
    class_size    INT := 0;
    class_members INT := 0;
    overrides     REFCURSOR  := $1;
BEGIN
    SELECT students_enrolled.courseName, COUNT(*)
    FROM students_enrolled
    GROUP BY students_enrolled.courseName, COUNT(*) INTO class_members;

    SELECT Sections.classSize
    FROM Sections
    INNER JOIN Enrollment ON Enrollment.courseID = Sections.courseID
    WHERE Enrollment.sectionNumber = Sections.sectionNumber
    INTO class_members;

    IF class_size >= class_members THEN
    OPEN overrides FOR
            SELECT students_enrolled.fname, students_enrolled.lname, students_enrolled.courseName, SUM(Sections.classSizeCap - Sections.classSize) AS overrides
             FROM students_enrolled
             INNER JOIN Sections ON Sections.courseID = students_enrolled.courseID
                                 AND Sections.sectionNumber = students_enrolled.sectionNumber
             GROUP BY students_enrolled.fname, students_enrolled.lname, students_enrolled.courseName, SUM(Sections.classSizeCap - Sections.classSize)
             ;
    END IF;
    RETURN overrids;
END
$$
LANGUAGE plpgsql;

【讨论】:

感谢您的帮助。只是为了确保我理解正确,您的意思是将值放在存储过程的 DECLARE 部分,将 SELECT 更改为 PERFORM,然后使用变量名来比较值? 是的,抱歉不够精确 哎呀,我知道我真的把你弄糊涂了。在您的情况下,我对 PERFORM 的看法是错误的: 哦,对不起,怎么回事? 我用似乎可行的方法编辑了答案,但没有数据我无法保证它完全有效。【参考方案2】:

语法:

OPEN unbound_cursor FOR query;

CASE ... 不是查询。以SELECT 开始查询,并将谓词放入SELECTWHERE 子句中。

【讨论】:

哦,好吧,所以我必须修改一些东西才能使它与 CASE 一起工作。谢谢!【参考方案3】:

因此,与其比较班级规模属性,我意识到最好只进行查询,说明谁参加了哪个班级,按学分顺序显示特定班级的这些人,然后在classSizeCap 值。

这可以在LIMIT 之后完成,您可以指定一个限制金额,然后使用OFFSET 指示您要从哪里开始。然后,您可以使用所需的类和部分调用该函数。

-- 将显示学生需要覆盖哪个课程 -- 创建或替换函数 startOverrides(INT, INT, REFCURSOR) RETURNS refcursor AS $$ 宣布 类 INT := $1; 部分 INT := $2; class_size INT := (SELECT classSizeCap FROM Sections WHERE courseID = class AND sectionNumber = section); 覆盖 REFCURSOR := $3; 开始 OPEN 覆盖 FOR SELECT * FROM students_enrolled WHERE (courseID = class AND sectionNumber = section) ORDER BY creditsEarned DESC LIMIT 1844674 OFFSET class_size; RETURN 覆盖; 结尾 $$ 语言 plpgsql; SELECT startOverrides(222, 112, 'overrides'); FETCH ALL FROM 覆盖;

【讨论】:

以上是关于如何检查存储过程中两个 SELECT 语句的输出是不是相等、大于或小于?的主要内容,如果未能解决你的问题,请参考以下文章

从数据访问对象中的存储过程中返回两个 select 语句的值

oracle存储过程如何输出信息

sqlserver 存储过程 保存在哪张表里如何通过select语句查询哪些存储过程是包含某个关键词

如何在 Redshift 中的 select 语句中使用存储过程

如何在 select 语句的列列表中使用存储过程的结果?

如何在带有 Select 语句的存储过程上使用 LINQ?