2016-02-11 56 views
1

我設置了一個遊標來獲取我的過程結果中的多行。但是,它似乎不會生成此錯誤消息: 「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

我會像改寫如下:但

open find; 
loop 
fetch find into find_rec; 
Exit when find%NOTFOUND; 
... 
end loop; 
close find; 

,爲什麼你打開這個遊標,如果你沒有在內心的選擇使用它的價值? 但是,我認爲會產生錯誤,因爲光標內的選擇在一次或多次迭代中返回兩個或更多行。 欲瞭解更多信息,請參閱,例如,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; 
+0

我試圖用你的方法來重寫代碼,但它也不起作用。 「光標內部的選擇在一次或多次迭代中返回兩行或多行」是什麼意思?是不是遊標被用來處理多行? –

+0

在遊標的每次迭代中,select必須返回一行以允許設置變量:變量 - 「一個值」。因此,在迭代中,如果select返回,例如兩個記錄,那麼在aterm,asectno,asid,ascore變量中插入哪些值?第一行的值?第二行的值? – Yellow75

+0

我明白這一點。但是,如何在我的代碼中發生?你是說我的光標沒有正確定義,或者我沒有正確使用它?我該如何解決這個問題?謝謝。 –

相關問題