我有一项任务要求我重写我为之前任务编写的PL / SQL代码:
DECLARE
-- Variables used to count a, b, c, d, and f grades:
na integer := 0;
nb integer := 0;
nc integer := 0;
nd integer := 0;
nf integer := 0;
BEGIN
select count(*) into na
from gradeReport1
where grade = 'A';
select count(*) into nb
from gradeReport1
where grade = 'B';
select count(*) into nc
from gradeReport1
where grade = 'C';
select count(*) into nd
from gradeReport1
where grade = 'D';
select count(*) into nf
from gradeReport1
where grade = 'F';
if na > 0 then
DBMS_OUTPUT.PUT_LINE('There are total ' || na || ' A''s');
else
DBMS_OUTPUT.PUT_LINE('There are no As');
end if;
if nb > 0 then
DBMS_OUTPUT.PUT_LINE('There are total ' || nb || ' B''s');
else
DBMS_OUTPUT.PUT_LINE('There are no Bs');
end if;
if nc > 0 then
DBMS_OUTPUT.PUT_LINE('There are total ' || nc || ' C''s');
else
DBMS_OUTPUT.PUT_LINE('There are no Cs');
end if;
if nd > 0 then
DBMS_OUTPUT.PUT_LINE('There are total ' || nd || ' D''s');
else
DBMS_OUTPUT.PUT_LINE('There are no Ds');
end if;
if nf > 0 then
DBMS_OUTPUT.PUT_LINE('There are total ' || nf || ' F''s');
else
DBMS_OUTPUT.PUT_LINE('There are no Fs');
end if;
END;
所有这一切都是搜索我制作的名为gradeReport的表格,该表格存储了学生ID并将其与成绩相关联。 PL / SQL计算A级到F级的所有实例。问题是我要使用循环和VARRAYS重写此解决方案。任何人都可以给我一些提示来帮助我为我滚球吗?我只使用PL / SQL几个星期,并没有比语法的基本理解更多,所以我完全迷失了,不知道从哪里开始。
这里没有寻找任何答案,只是一些想法。
谢谢
答案 0 :(得分:1)
答案 1 :(得分:1)
编辑:由于要求专门针对varrays,请参阅AmmoQ和MTO的回复。但是,正如他们都指出的那样,在实践中你不太可能需要这类任务的数组,即使你这样做了,你也会使用nested table或associative array而不是{{} {3}} 的
你需要一个varray,与
一致for r in (
select grade from gradereport1
)
loop
...
end loop;
在实际代码中,您可能会进行group by
查询并让SQL为您进行计数。
然后根据r.grade
的值,有条件地增加循环中的计数器。
您可以合理化所有if
语句,以便通过编写一个获得成绩和总计的程序来报告总计,因为所有这些都是相同的逻辑。
procedure showgrade
( p_grade gradereport1.grade%type
, p_count integer )
is
begin
...
end showgrade;
我会将细节留作练习。
只是为了好玩,这是另一种方法,使用数组和循环(但不是varray - 它们确实有点无用):
declare
type gradereport_tt is table of pls_integer index by gradereport.grade%type;
gradecounts gradereport_tt;
g gradereport.grade%type;
begin
-- Initialise counts:
gradecounts('A') := 0;
gradecounts('B') := 0;
gradecounts('C') := 0;
gradecounts('D') := 0;
gradecounts('E') := 0;
gradecounts('F') := 0;
-- Count grades:
for r in (
select grade from gradereport
)
loop
gradecounts(r.grade) := gradecounts(r.grade) +1;
end loop;
-- Report counts:
g := gradecounts.first;
while g is not null loop
dbms_output.put_line(g || ': ' || gradecounts(g));
g := gradecounts.next(g);
end loop;
end;
顺便说一句,除了条件包含需要分离的if
和and
条件的混合之外,没有必要像or
一样放置括号。
也没有必要用大写写任何东西。这很常见,Cursor FOR loop一直都是这样,但是他们在HTML / CSS世界中进行了这场辩论,并以小写字母为可读性。如果您打算使用大写规则,至少要始终如一地使用它。您的代码示例包含end if;
但END;
更不用说Select
(我已修复)。有些人似乎能够阅读这样的代码而不会让他们疯狂,但我担心我不是其中之一。
答案 2 :(得分:1)
DECLARE
-- Need to ensure the array size will hold all the grades
TYPE grade_tab IS VARRAY(200) OF gradeReport1.grade%TYPE;
-- variable used to store the grades:
t_grades grade_tab;
-- Variables used to count a, b, c, d, and f grades:
na INTEGER;
nb INTEGER;
nc INTEGER;
nd INTEGER;
nf INTEGER;
BEGIN
-- Store the grades in an array:
SELECT grade
BULK COLLECT INTO t_grades
FROM gradeReport1
WHERE grade IN ( 'A', 'B', 'C', 'D', 'F' );
-- Loop through the grades and count how many of each:
FOR i IN 1 .. t_grades.COUNT LOOP
IF t_grades(i) = 'A' THEN na := na + 1;
ELSIF t_grades(i) = 'B' THEN nb := nb + 1;
ELSIF t_grades(i) = 'C' THEN nc := nc + 1;
ELSIF t_grades(i) = 'D' THEN nd := nd + 1;
ELSIF t_grades(i) = 'F' THEN nf := nf + 1;
END IF;
END LOOP;
-- Output grade counts
END;
/
但是,更简单的解决方案是在单个SQL查询中进行计数(尽管这不符合评估使用VARRAY
的要求):
DECLARE
-- Variables used to count a, b, c, d, and f grades:
na INTEGER;
nb INTEGER;
nc INTEGER;
nd INTEGER;
nf INTEGER;
BEGIN
SELECT COUNT( CASE grade WHEN 'A' THEN 1 END ),
COUNT( CASE grade WHEN 'B' THEN 1 END ),
COUNT( CASE grade WHEN 'C' THEN 1 END ),
COUNT( CASE grade WHEN 'D' THEN 1 END ),
COUNT( CASE grade WHEN 'F' THEN 1 END )
INTO na,
nb,
nc,
nd,
nf
FROM gradeReport1;
-- Output grade counts...
END;
/
答案 3 :(得分:0)
使用VARRAY的解决方案可能如下所示:
change_column :tippies, :tip, :float, null: true, default: 0
但老实说,在这种情况下使用VARRAYs毫无意义。只需使用游标循环:
DECLARE
type chararray IS VARRAY(6) OF CHAR(1);
type numarray IS VARRAY(6) OF INTEGER;
grades chararray;
cnt numarray;
BEGIN
select grade, count(*)
bulk collect into grades, cnt
from gradeReport1
group by grade
order by grade;
for i in 1..grades.count loop
DBMS_OUTPUT.PUT_LINE('There are total ' || cnt(i) || ' ' ||grades(i)||'s');
end loop;
END;
/
但是,找到缺失的标记(计数为0的标记)有点困难。