PL/SQL 写一个更新列的程序?
PL/SQL Write a procedure to update a column?
我应该根据程序
将学生成绩更新为 'A'
ChangeGrade(p_sID, p_classID)
如果学生未在 class (p_classID) 中注册,则会打印一条错误消息。
这里是 table:
正在注册
sID classID Grade
*** ******* *****
104 10440 B
102 10220 C
... ..... .
我应该做一个内连接吗?这是我拥有的:
Create or Replace ChangeGrade (
p_sID enrolling.sID%type
p_classID enrolling.classID%type )
AS
p_id_enrolled NUMBER;
BEGIN
SELECT sID into p_id_enrolled
FROM Enrolling
WHERE sID = p_sID
AND classID = p_classID
IF p_sID = p_id_enrolled THEN
update Enrolling
set GRADE = 'A'
dbms_output.put_line('Student grade has been changed.')
ELSE
dbms_output.put_line('Student record does not exist.')
END IF;
END;
/
我不知道打印出什么样的错误,但你好像漏掉了';'在某些命令的结尾(在 if 语句中和 select 之后)。
正如我在评论中提到的,您的程序中有几个地方缺少 semicolon
(行终止符)。试试这个:
CREATE OR REPLACE Procedure ChangeGrade (
p_sID enrolling.sID%type
p_classID enrolling.classID%type )
AS
p_id_enrolled NUMBER;
BEGIN
SELECT sID
INTO p_id_enrolled
FROM Enrolling
WHERE sID = p_sID AND classID = p_classID;
IF p_sID = p_id_enrolled
THEN
UPDATE Enrolling
SET GRADE = 'A'
WHERE sID = p_sID;
DBMS_OUTPUT.put_line ('Student grade has been changed.');
ELSE
DBMS_OUTPUT.put_line ('Student record does not exist.');
END IF;
EXCEPTION
WHEN NO_DATA_FOUND Then
dbms_output.put_line('Student record does not exist for this class');
END;
/
您需要将学生不在 class 中的事实作为例外处理:
Create or Replace PROCEDURE ChangeGrade (
p_sID enrolling.sID%type,
p_classID enrolling.classID%type,
p_grade enrolling.grade%type )
AS
l_enrolled NUMBER;
BEGIN
SELECT sID INTO l_enrolled
FROM Enrolling
WHERE sID = p_sID
AND classID = p_classID;
IF l_enrolled = p_sID THEN
update Enrolling set GRADE = p_grade WHERE sID = p_sID and classID = p_classID;
dbms_output.put_line('Student grade has been changed.');
END IF;
EXCEPTION WHEN NO_DATA_FOUND
dbms_output.put_line('Student record does not exist for this class');
END;
/
我还为成绩添加了一个参数,因为通过它也是合乎逻辑的。
您的代码中存在以下问题:
这个查询没有意义:
SELECT sID into p_id_enrolled
FROM Enrolling
WHERE sID = p_sID
AND classID = p_classID
你 select sID
变成了 p_id_enrolled
,但是在 WHERE
子句中你过滤了 sID = p_sID
,所以 p_id_enrolled
总是等于p_sID
,你根本不需要这个 select 语句。
这条更新语句更新整个table:
UPDATE Enrolling
SET GRADE = 'A';
您需要添加一个过滤子句以仅更新一行。
如果学生没有在 class 注册,查询 returns 没有行,你会得到 NO_DATA_FOUND
异常。要处理它,您需要捕获异常或计算学生数。
我建议使用以下内容:
Create or Replace procedure ChangeGrade (
p_sID enrolling.sID%type,
p_classID enrolling.classID%type )
AS
cnt NUMBER;
BEGIN
SELECT count(*) into cnt
FROM Enrolling
WHERE sID = p_sID
AND classID = p_classID;
IF cnt = 1 THEN
update Enrolling
set GRADE = 'A'
where sID = p_sID
AND classID = p_classID;
dbms_output.put_line('Student grade has been changed.');
ELSE
dbms_output.put_line('Student record does not exist.');
END IF;
END;
/
Create or Replace procedure ChangeGrade (
p_sID enrolling.sID%type
p_classID enrolling.classID%type )
AS
BEGIN
update Enrolling
set GRADE = 'A'
where sID = p_sID
AND classID = p_classID;
IF SQL%ROWCOUNT > 0 THEN
dbms_output.put_line('Student grade has been changed.');
ELSE
dbms_output.put_line('Student record does not exist.');
END IF;
END;
您也可以使用光标,然后查看学生是否注册了该课程。如果 he/she 是,则更新成绩。我认为游标比 SELECT X INTO n
更安全,因为当您尝试插入 NULL
、SELECT NULL INTO n
时确实会出现丑陋的错误,而且这些错误通常很难找到。
例如:
CREATE OR REPLACE ChangeGrade (p_sID enrolling.sID%TYPE,
p_classID enrolling.classID%TYPE)
AS
CURSOR cEnrolling IS
SELECT *
FROM Enrolling
WHERE SID = p_sID
AND classID = p_classID;
rEnrolling cEnrolling%ROWTYPE;
BEGIN
OPEN cEnrolling;
FETCH cEnrolling INTO rEnrolling;
IF cEnrolling%FOUND THEN
-- Student record found.
UPDATE Enrolling
SET Grade = 'A'
WHERE SID = rEnrolling.sId;
DBMS_OUTPUT.PUT_LINE('Student grade has been changed.');
ELSE
-- Student record not found.
DBMS_OUTPUT.PUT_LINE('Student record does not exist.');
END IF;
CLOSE cEnrolling;
END;
/
我应该根据程序
将学生成绩更新为 'A'ChangeGrade(p_sID, p_classID)
如果学生未在 class (p_classID) 中注册,则会打印一条错误消息。
这里是 table:
正在注册
sID classID Grade
*** ******* *****
104 10440 B
102 10220 C
... ..... .
我应该做一个内连接吗?这是我拥有的:
Create or Replace ChangeGrade (
p_sID enrolling.sID%type
p_classID enrolling.classID%type )
AS
p_id_enrolled NUMBER;
BEGIN
SELECT sID into p_id_enrolled
FROM Enrolling
WHERE sID = p_sID
AND classID = p_classID
IF p_sID = p_id_enrolled THEN
update Enrolling
set GRADE = 'A'
dbms_output.put_line('Student grade has been changed.')
ELSE
dbms_output.put_line('Student record does not exist.')
END IF;
END;
/
我不知道打印出什么样的错误,但你好像漏掉了';'在某些命令的结尾(在 if 语句中和 select 之后)。
正如我在评论中提到的,您的程序中有几个地方缺少 semicolon
(行终止符)。试试这个:
CREATE OR REPLACE Procedure ChangeGrade (
p_sID enrolling.sID%type
p_classID enrolling.classID%type )
AS
p_id_enrolled NUMBER;
BEGIN
SELECT sID
INTO p_id_enrolled
FROM Enrolling
WHERE sID = p_sID AND classID = p_classID;
IF p_sID = p_id_enrolled
THEN
UPDATE Enrolling
SET GRADE = 'A'
WHERE sID = p_sID;
DBMS_OUTPUT.put_line ('Student grade has been changed.');
ELSE
DBMS_OUTPUT.put_line ('Student record does not exist.');
END IF;
EXCEPTION
WHEN NO_DATA_FOUND Then
dbms_output.put_line('Student record does not exist for this class');
END;
/
您需要将学生不在 class 中的事实作为例外处理:
Create or Replace PROCEDURE ChangeGrade (
p_sID enrolling.sID%type,
p_classID enrolling.classID%type,
p_grade enrolling.grade%type )
AS
l_enrolled NUMBER;
BEGIN
SELECT sID INTO l_enrolled
FROM Enrolling
WHERE sID = p_sID
AND classID = p_classID;
IF l_enrolled = p_sID THEN
update Enrolling set GRADE = p_grade WHERE sID = p_sID and classID = p_classID;
dbms_output.put_line('Student grade has been changed.');
END IF;
EXCEPTION WHEN NO_DATA_FOUND
dbms_output.put_line('Student record does not exist for this class');
END;
/
我还为成绩添加了一个参数,因为通过它也是合乎逻辑的。
您的代码中存在以下问题:
这个查询没有意义:
SELECT sID into p_id_enrolled FROM Enrolling WHERE sID = p_sID AND classID = p_classID
你 select
sID
变成了p_id_enrolled
,但是在WHERE
子句中你过滤了sID = p_sID
,所以p_id_enrolled
总是等于p_sID
,你根本不需要这个 select 语句。这条更新语句更新整个table:
UPDATE Enrolling SET GRADE = 'A';
您需要添加一个过滤子句以仅更新一行。
如果学生没有在 class 注册,查询 returns 没有行,你会得到
NO_DATA_FOUND
异常。要处理它,您需要捕获异常或计算学生数。
我建议使用以下内容:
Create or Replace procedure ChangeGrade (
p_sID enrolling.sID%type,
p_classID enrolling.classID%type )
AS
cnt NUMBER;
BEGIN
SELECT count(*) into cnt
FROM Enrolling
WHERE sID = p_sID
AND classID = p_classID;
IF cnt = 1 THEN
update Enrolling
set GRADE = 'A'
where sID = p_sID
AND classID = p_classID;
dbms_output.put_line('Student grade has been changed.');
ELSE
dbms_output.put_line('Student record does not exist.');
END IF;
END;
/
Create or Replace procedure ChangeGrade (
p_sID enrolling.sID%type
p_classID enrolling.classID%type )
AS
BEGIN
update Enrolling
set GRADE = 'A'
where sID = p_sID
AND classID = p_classID;
IF SQL%ROWCOUNT > 0 THEN
dbms_output.put_line('Student grade has been changed.');
ELSE
dbms_output.put_line('Student record does not exist.');
END IF;
END;
您也可以使用光标,然后查看学生是否注册了该课程。如果 he/she 是,则更新成绩。我认为游标比 SELECT X INTO n
更安全,因为当您尝试插入 NULL
、SELECT NULL INTO n
时确实会出现丑陋的错误,而且这些错误通常很难找到。
例如:
CREATE OR REPLACE ChangeGrade (p_sID enrolling.sID%TYPE,
p_classID enrolling.classID%TYPE)
AS
CURSOR cEnrolling IS
SELECT *
FROM Enrolling
WHERE SID = p_sID
AND classID = p_classID;
rEnrolling cEnrolling%ROWTYPE;
BEGIN
OPEN cEnrolling;
FETCH cEnrolling INTO rEnrolling;
IF cEnrolling%FOUND THEN
-- Student record found.
UPDATE Enrolling
SET Grade = 'A'
WHERE SID = rEnrolling.sId;
DBMS_OUTPUT.PUT_LINE('Student grade has been changed.');
ELSE
-- Student record not found.
DBMS_OUTPUT.PUT_LINE('Student record does not exist.');
END IF;
CLOSE cEnrolling;
END;
/