我设置了一个游标来获取我的过程结果中的多行。但是,它似乎通过生成此错误消息不起作用: “01422. 00000 - ”确切的提取返回超过请求的行数“ *原因:精确提取中指定的数字小于返回的行数。 *操作:重写查询或更改请求的行数“
代码的其他部分没有问题,因为当我只有一条记录时我试过,它运行正常。但是当有多个记录时,我的光标似乎不起作用。那是为什么?
set serveroutput on
declare
get_term scores.term%type;
get_sectno scores.sectno%type;
get_sid scores.sid%type;
get_score scores.points%type;
status boolean;
procedure total_score (aterm in out scores.term%type,
asectno in out scores.sectno%type,
asid out scores.sid%type,
ascore out scores.points%type,
status out boolean)
is
cursor find is
select scores.term, scores.sectno, sid, sum(points/maxpoints*weight)
from scores, components
where scores.term=components.term
and scores.sectno=components.sectno
group by scores.term, scores.sectno, sid;
find_rec find%rowtype;
begin
open find;
fetch find into find_rec;
while find%found loop
select scores.term, scores.sectno, sid, sum(points/maxpoints*weight)
into aterm, asectno, asid, ascore
from scores, components
where scores.term=components.term
and scores.term=aterm
and scores.sectno=components.sectno
and scores.sectno=asectno
and scores.compname=components.compname
group by scores.term, scores.sectno, sid;
status:=true;
fetch find into find_rec;
end loop;
close find;
exception
when no_data_found then
status:=false;
end;
begin
get_term:='F12';
get_sectno:='1031';
total_score (get_term, get_sectno, get_sid, get_score, status);
if (status) then
dbms_output.put_line(get_term||' '||get_sectno||' '||get_sid||' '||get_score);
else
dbms_output.put_line('Record not found.');
end if;
end;
答案 0 :(得分:0)
我会改写如下:
open find;
loop
fetch find into find_rec;
Exit when find%NOTFOUND;
...
end loop;
close find;
但是,如果您不在内部选择中使用其值,为什么要打开此光标? 但是,我认为生成错误是因为游标内部的select会在一次或多次迭代中返回两行或更多行。 有关更多信息,请参阅,例如http://www.oracle.com/technetwork/issue-archive/2013/13-mar/o23plsql-1906474.html。再见,伊戈尔
更新
CREATE TABLE SCORES(SID INTEGER, TERM VARCHAR2(10), SECTNO VARCHAR2(10), COMPNAME VARCHAR2(50));
CREATE TABLE COMPONENTS(TERM VARCHAR2(10), SECTNO VARCHAR2(10), COMPNAME VARCHAR2(50), POINTS INTEGER, MAXPOINTS INTEGER, WEIGHT INTEGER);
INSERT ALL
INTO SCORES VALUES(1,'AAA', 'BBB', 'CCC')
INTO SCORES VALUES(5,'AAA', 'BBB', 'CCC')
INTO SCORES VALUES(2,'DDD', 'EEE', 'FFF')
INTO SCORES VALUES(3,'GGG', 'HHH', 'III')
SELECT * FROM DUAL;
INSERT ALL
INTO COMPONENTS VALUES('AAA', 'BBB', 'CCC', 1, 2, 3)
INTO COMPONENTS VALUES('DDD', 'EEE', 'FFF', 4, 5, 6)
INTO COMPONENTS VALUES('GGG', 'HHH', 'III', 7, 8, 9)
SELECT * FROM DUAL;
COMMIT;
CREATE OR REPLACE PROCEDURE TOTAL_SCORE (ATERM in OUT SCORES.TERM%type,
ASECTNO in OUT SCORES.SECTNO%type) AS
cursor find (cpAterm VARCHAR2, cpAsectno VARCHAR2) is
select scores.term, scores.sectno, sid, sum(points/maxpoints*weight) AS SUM_SCORE
from scores RIGHT JOIN components ON
scores.term=components.term
and scores.sectno=components.sectno
and scores.compname=components.compname
WHERE
scores.term=cpAterm
AND scores.sectno=cpAsectno
group by scores.term, scores.sectno, sid;
find_rec find%rowtype;
counter INTEGER:=0;
BEGIN
open find(ATERM, ASECTNO);
LOOP
fetch find into find_rec;
exit when find%notfound;
--DBMS_OUTPUT.PUT_LINE(find_rec.TERM||' '||find_rec.sectno||' '||find_rec.SID||' '||find_rec.SUM_SCORE);
if (find_rec.term IS NOT NULL) then
dbms_output.put_line(find_rec.TERM||' '||find_rec.sectno||' '||find_rec.SID||' '||find_rec.SUM_SCORE);
counter:=counter+1;
END IF;
end loop;
close find;
if counter = 0 then
dbms_output.put_line('NO DATA FOUND FOR: ' || ATERM || ', ' || ASECTNO);
end if;
END;
/
SET SERVEROUTPUT ON
DECLARE
get_term VARCHAR2(10);
get_sectno VARCHAR2(10);
begin
get_term:='AAA';
get_sectno:='BBB';
total_score (get_term, get_sectno);
END;
/
DROP TABLE SCORES;
DROP TABLE COMPONENTS;