2015-11-20 15 views
1
DECLARE 
    i  employees.first_name%TYPE; 
    a  employees.last_name%TYPE; 
    j  employees.salary%TYPE; 
    v_cnt NUMBER; 

    CURSOR c1 IS 
    SELECT first_name 
      ,last_name 
      ,salary 
     FROM employees 
    WHERE employee_id BETWEEN 100 AND 105; 

BEGIN 
    OPEN c1; 

    LOOP 
    FETCH c1 INTO i, a, j; 

    dbms_output.put_line(i || ' ' || a || ' SALARY IS ' || j || ' row count is ' || v_cnt); 

    v_cnt := c1%ROWCOUNT;  
    EXIT WHEN c1%NOTFOUND; 
    END LOOP; 

    CLOSE c1; 
END; 
/

我上面的查詢基本上遍歷100和105,並打印出所有6名員工的工資之間的所有employee_id遊標屬性%NOTFOUND作爲退出語句中使用<code>dbms_output.put_line</code>返回混亂的結果

但是,我得到7個結果與上一個記錄的重複結果的最後一個。見下面

Steven King SALARY IS 24000 row count is 
Neena Kochhar SALARY IS 17000 row count is 1 
Lex De Haan SALARY IS 17000 row count is 2 
Alexander Hunold SALARY IS 9000 row count is 3 
Bruce Ernst SALARY IS 6000 row count is 4 
David Austin SALARY IS 4800 row count is 5 
David Austin SALARY IS 4800 row count is 6 

爲什麼我的結果會像這樣返回?爲什麼不是我的遊標rowcount將第一條記錄標記爲1?

+0

假設'David Austin'在你的數據中有兩次,僱員ID爲100到105.至於第一個'v_cnt'值。 。 。它缺少,因爲它在* put_line()之後被初始化,而不是之前。 –

+0

你可以發表你的意見嗎?我的意思是員工表的內容 – SriniV

回答

2
  1. v_cnt未初始化,即對dbms_output.put_line第一次調用IS NULL,讓你看到一個空行,而不是在輸出行號。
  2. 最後一次讀取不作任何操作,因爲遊標中沒有更多行,所以變量i, a, j在上次讀取後不會更改。您可以隨意獲取,但在從光標中取出最後一行後,FETCH INTO運算符不會生成新數據。

爲了得到你所需要的(標準循環行爲)的取環,應組織爲

LOOP 
    FETCH c1 INTO i, a, j; 
    EXIT WHEN c1%NOTFOUND; 
    v_cnt := c1%ROWCOUNT; 

    dbms_output.put_line(i || ' ' || a || ' SALARY IS ' || j || ' row count is ' || v_cnt); 

END LOOP; 

要避免獲取光標,你可以用做「for循環」 compliactions。 在大多數情況下,這是一個合適的解決方案,並且絕對是您在問題中給出的示例。

FOR l_rec IN c1 
LOOP 

    i := l_rec.first_name; 
    a := l_rec.last_name; 
    j := l_rec.salary; 
    v_cnt := c1%ROWCOUNT; 

    dbms_output.put_line(i || ' ' || a || ' SALARY IS ' || j || ' row count is ' || v_cnt); 

END LOOP;