2015-10-21 89 views
1

我正在使用Oracle XE的HR數據庫學習PL/SQL。如何在匿名PL/SQL塊中使用out遊標參數執行oracle過程?

我創建了以下存儲過程:

CREATE OR REPLACE PROCEDURE get_employees(p_country_id IN CHAR 
             , p_emp  OUT SYS_REFCURSOR) 
IS 
BEGIN 

    OPEN p_emp FOR 
    SELECT e.first_name 
      ,e.last_name 
      ,e.department_id 
      ,d.department_name 
      ,l.city 
      ,l.state_province 
     FROM employees e 
    INNER JOIN departments d 
     ON e.department_id = d.department_id 
    INNER JOIN locations l 
     ON d.location_id = l.location_id 
    WHERE l.country_id = p_country_id; 
END; 

我知道如何在SQL開發GUI界面執行它,並查看結果。我也從Justin Cave處瞭解到herehere如何執行它並查看結果SQL * Plus的風格像這樣:

VARIABLE CE REFCURSOR; 
EXEC GET_EMPLOYEES('US', :CE); 
PRINT CE; 

我想在一個匿名PL/SQL塊執行存儲過程和看在網格中的結果,但它並沒有成功。

像什麼賈斯汀洞的建議,下面執行得很好,但結果不顯示:

DECLARE 
    C_EMP SYS_REFCURSOR; 
BEGIN 
    GET_EMPLOYEES('US', C_EMP); 
END; 

下會失敗:

DECLARE 
    C_EMP SYS_REFCURSOR; 
    L_REC C_EMP%ROWTYPE; --THIS LINE FAILS. 
BEGIN 
    GET_EMPLOYEES('US', C_EMP); 
    -- LOOP AND FETCH GOES HERE. 
END; 

錯誤消息說:

PLS-00320:此表達式類型的聲明是 不完整或格式不正確

我不明白。我一直在其他一些匿名的PL/SQL塊中這樣做,並且它工作得很好。這條線有什麼問題?無法弄清楚。

+1

引用遊標與普通遊標不相同;你在其他方塊中做了什麼 - 使用普通光標的rowtpe? [你不能這樣做](http://stackoverflow.com/q/11187376/266304),但我不知道如何做到這一點無論如何會幫助你。我不完全確定你的問題是什麼 - 爲什麼你會得到這個錯誤,或者你在尋找如何在網格視圖中獲取引用光標?或者是其他東西? –

+1

[This answer](http://stackoverflow.com/a/27006514/266304)還顯示了一種通過代碼編輯器對話框在網格中獲取結果的方法。這可能是這些問題之一的重複,但不確定哪一個。 –

+0

@AlexPoole:我想我已經明確了我一直在試圖做的事情:'我想在一個匿名的PL/SQL塊中執行存儲過程,並在網格中查看結果,但它並未成功。' – Stack0verflow

回答

2

我想你是誤解了%ROWTYPE的使用。當您存儲表中的所有行時,應該只使用%ROWTYPE。不要使用%ROWTYPE,而應根據您要提取的列的數據類型創建自己的類型(記錄)。試試這個:

DECLARE 
    C_EMP SYS_REFCURSOR; 
    TYPE new_type IS RECORD(FIRST_NAME VARCHAR2(100), LAST_NAME VARCHAR2(200), DEPARTMENT_ID NUMBER, DEPARTMENT_NAME VARCHAR2(200), CITY VARCHAR2(200), STATE_PROVINCE VARCHAR2(200)); 
    L_REC new_type; --instead of using %ROWTYPE, use the declared type 
BEGIN 
    GET_EMPLOYEES('US', C_EMP); 
    LOOP 
FETCH c_emp INTO l_rec; 
EXIT WHEN c_emp%NOTFOUND; 

    dbms_output.put_line(l_rec.first_name||'_'|| 
          l_rec.last_name||'_'|| 
          l_rec.department_id||'_'|| 
          l_rec.department_name||'_'|| 
          l_rec.city||'_'|| 
          l_rec.state_province); 
END LOOP; 

CLOSE c_emp; 
END; 
+0

謝謝。你的意思是表中的所有*列?你是否指出%rowtype只能應用於靜態遊標? – Stack0verflow

1

我敢肯定這個問題沒有簡短的答案。

要了解問題所在,應該調查強類型和弱類型的refcursors。

Oracle DBMS沒有內置工具將refcursor結果放入網格中。如果你想寫一個DBMS_SQL包和動態PL/SQL,你可以編寫一個程序來產生你期望的結果(即把任何sys_refcursor放入網格中)。

但是,如果你剛開始學習PL/SQL,請不要浪費你的時間 - 首先,獲得一些經驗,你會看到如何去做。只要沒有發生,使用SQL Developer的hack

+0

感謝您告訴我,沒有內置工具將refcursor結果放入網格中。我在我原來的文章中說過,我知道如何通過SQL Developer GUI界面查看結果,這就是你正在討論的黑客攻擊。 – Stack0verflow

+0

@ StackOverflow,那麼你是什麼意思的「網格」?描述你想解決你的問題的「理想界面」。 PS:我看到唯一的問題「這裏有什麼問題?」。我認爲如果你得到這樣的答案,你就不會滿意:「定義弱引用遊標的%ROWTYPE是錯誤的,因爲在編譯時rowtype是未知的。」所以我問你 - 你想得到什麼? – diziaq

+0

謝謝。因此,正如我們所知,SQL Developer能夠在網格中顯示引用遊標結果集,這是您提到的黑客攻擊。但是SQL Developer沒有向我們展示生成的腳本(比如SQL Server Management Studio)。所以我想問題是,SQL Developer如何做到這一點? – Stack0verflow