Plsql 为什么我的光标不能正常工作?
我设置了一个游标来获取过程结果中的多行。但是,生成以下错误消息似乎不起作用: “01422.00000-“精确提取返回的行数超过请求的行数” *原因:精确提取中指定的行数小于返回的行数。 *操作:重写查询或更改请求的行数“ 代码的其他部分没有问题,正如我在只有一条记录时尝试的那样,它运行良好。但当有多条记录时,我的光标似乎不起作用。为什么呢Plsql 为什么我的光标不能正常工作?,plsql,cursor,procedure,Plsql,Cursor,Procedure,我设置了一个游标来获取过程结果中的多行。但是,生成以下错误消息似乎不起作用: “01422.00000-“精确提取返回的行数超过请求的行数” *原因:精确提取中指定的行数小于返回的行数。 *操作:重写查询或更改请求的行数“ 代码的其他部分没有问题,正如我在只有一条记录时尝试的那样,它运行良好。但当有多条记录时,我的光标似乎不起作用。为什么呢 set serveroutput on declare get_term scores.term%type; get_sectno score
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;
我想重写如下:
open find;
loop
fetch find into find_rec;
Exit when find%NOTFOUND;
...
end loop;
close find;
但是,如果不在内部选择中使用其值,为什么要打开此光标?
但是,我认为产生错误是因为游标中的select在一次或多次迭代中返回两行或多行。
有关更多信息,请参见,例如。再见,伊戈尔
更新:
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;
我想重写如下:
open find;
loop
fetch find into find_rec;
Exit when find%NOTFOUND;
...
end loop;
close find;
但是,如果不在内部选择中使用其值,为什么要打开此光标?
但是,我认为产生错误是因为游标中的select在一次或多次迭代中返回两行或多行。
有关更多信息,请参见,例如。再见,伊戈尔
更新:
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;
我试图用你的方法重写代码,但也不起作用。“光标内的select在一次或多次迭代中返回两行或多行”是什么意思?光标不是用来处理多行吗?在光标的每次迭代中,select必须只返回一行,以允许设置变量:变量-->值。因此,在迭代中,如果select返回两条记录,那么在aterm、asectno、asid、ascore变量中插入什么值?第一行的值是多少?第二行的值是多少?我明白。但在我的代码中会发生什么呢?你是说我的游标定义不正确还是我没有正确使用它?我如何解决这个问题?谢谢。执行select:我认为它将检索两条或更多记录;如果是这样,例如,使用光标值进行过滤,以便每次迭代仅检索一行;例如:WHERE scores.term=find_rec.something。。。最后,我建议在from子句中使用join(从a.id=b.id等上的内部join b)。我想我正在使用光标访问多个记录。是,select语句将返回多行记录。但光标不是会从一行记录移动到另一行来处理所有记录吗?这不是循环的目的吗?我试图用你的方法重写代码,但它也不起作用。“光标内的select在一次或多次迭代中返回两行或多行”是什么意思?光标不是用来处理多行吗?在光标的每次迭代中,select必须只返回一行,以允许设置变量:变量-->值。因此,在迭代中,如果select返回两条记录,那么在aterm、asectno、asid、ascore变量中插入什么值?第一行的值是多少?第二行的值是多少?我明白。但在我的代码中会发生什么呢?你是说我的游标定义不正确还是我没有正确使用它?我如何解决这个问题?谢谢。执行select:我认为它将检索两条或更多记录;如果是这样,例如,使用光标值进行过滤,以便每次迭代仅检索一行;例如:WHERE scores.term=find_rec.something。。。最后,我建议在from子句中使用join(从a.id=b.id等上的内部join b)。我想我正在使用光标访问多个记录。是,select语句将返回多行记录。但光标不是会从一行记录移动到另一行来处理所有记录吗?这不是循环的目的吗?