2010-04-05 151 views
3

這個問題是相似的一對夫婦別人我已經在計算器上找到設置,但差異夠我signficant保證一個新的問題,所以在這裏它是:的結果獲得結果從動態SQL在Oracle中

我想獲得Oracle中動態SQL結果集,然後顯示它作爲一個的SQLDeveloper狀工具的結果集,就像如果我直接執行動態SQL語句。這是SQL Server簡單易懂,所以要具體,這裏是從SQL Server返回結果在SQL Server Management Studio或查詢瀏覽器設置一個例子:

EXEC sp_executesql N'select * from countries' 

或者更恰當:

DECLARE @stmt nvarchar(100) 
SET @stmt = N'select * from countries' 
EXEC sp_executesql @stmt 

問題"How to return a resultset/cursor from a Oracle PL/SQL anonymous block that executes Dynamic SQL?"解決了問題的前半部分 - 將動態SQL執行到遊標中。問題"How to make Oracle procedure return result sets"提供了類似的答案。網絡搜索已經揭示了同一主題的許多變體,都只涉及到我的問題的前半部分。我發現this post解釋瞭如何在SqlDeveloper中完成它,但是它使用了SqlDeveloper的一些功能。實際上,我使用的是自定義查詢工具,因此我需要將解決方案自包含在SQL代碼中。此自定義查詢工具同樣不具有顯示print(dbms_output.put_line)語句輸出的功能;它只顯示結果集。這裏還有one more possible avenue使用'execute immediate ... bulk collect',但是這個例子再次用dbms_output.put_line語句循環來呈現結果。 This link試圖解決這個問題,但這個問題從來沒有得到答案。

假定這是可能的,我會增加一個條件:我想這樣做而無需定義函數或過程(由於有限的DB權限)。也就是說,我想執行一個包含動態SQL的自包含PL/SQL塊,並在SqlDeveloper或類似工具中返回一個結果集。


所以總結:

  • 我想執行任意SQL語句(因此動態SQL)。
  • 該平臺是Oracle。
  • 該解決方案必須是一個沒有程序或功能的一個PL/SQL塊。
  • 輸出必須生成爲規範結果集;沒有打印報表。
  • 輸出必須呈現爲在設定的SQLDeveloper不使用任何的SQLDeveloper特殊功能的結果。

有什麼建議嗎?

回答

0

你似乎要求一個PL/SQL代碼塊,它將採用任意查詢返回未確定結構的結果集,並以某種方式「轉發/重構」結果集,以便可以通過某些方式輕鬆地呈現結果集「自定義GUI工具」。

如果是這樣,請查看DBMS_SQL以獲取動態SQL。它有一個DESCRIBE_COLUMNS過程,它從一個動態SELECT語句中返回列。你需要的步驟是,

  1. 解析聲明
  2. 描述結果集(列名和數據類型)
  3. 取每一行,併爲每列,調用數據類型相關的函數返回值到一個局部變量
  4. 將這些局部變量爲定義的結構返回到調用環境(如一致的列名[如COL_1,COL_2]可能是所有VARCHAR2的)

或者,您可以嘗試將查詢構建到XMLFOREST語句中,並將結果從XML中解析出來。


補充: 不同於SQL Server中,一個Oracle PL/SQL調用不會 '自然' 返回一個結果集。它可以打開一個或多個參考遊標並將它們傳回客戶端。然後,客戶有責任從這些ref遊標中獲取記錄和列。如果你的客戶不能處理這個問題,那麼你就不能使用PL/SQL調用。 存儲的函數可以返回一個預定義的集合類型,它可以讓你做一些類似於「select * from table(func_name('select * from countries'))」。然而,該函數不能執行DML(更新/刪除/插入/合併),因爲它吹掉了該查詢的任何一致性概念。加返回的結構是固定的,使得

select * from table(func_name('select * from countries')) 

必須返回相同的一組列(列名和數據類型)的作爲

select * from table(func_name('select * from persons')) 

這是可能的,使用DBMS_SQL或XMLFOREST,對於這樣的函數進行動態查詢並將其重新組合爲預定義的一組列(col_1,col_2等),以便可以以一致的方式返回。但我看不出它會是什麼。

+0

感謝您的意見,Gary。我不熟悉DBMS_SQL或XMLFOREST,所以我都讀了一下。也許我錯過了一些東西,但我不相信任何一種技術都會做我所要求的。關於你的DBMS_SQL建議,我看到2個問題。首先,它似乎需要預先了解目標聲明中的內容。其次,它不會讓我得到像SQL Server示例這樣的簡單結果集。一個解釋:是的,我正在使用一個自定義的GUI工具,但該解決方案必須首先使用PL/SQL代碼在SqlDeveloper中工作,而我不知道您提到的任何一種技術都可以做到這一點。 – 2010-04-07 14:56:59

0

試試這些。

DECLARE 
    TYPE EmpCurTyp IS REF CURSOR; 
    v_emp_cursor EmpCurTyp; 
    emp_record  employees%ROWTYPE; 
    v_stmt_str  VARCHAR2(200); 
    v_e_job   employees.job%TYPE; 
BEGIN 
    -- Dynamic SQL statement with placeholder: 
    v_stmt_str := 'SELECT * FROM employees WHERE job_id = :j'; 

    -- Open cursor & specify bind argument in USING clause: 
    OPEN v_emp_cursor FOR v_stmt_str USING 'MANAGER'; 

    -- Fetch rows from result set one at a time: 
    LOOP 
    FETCH v_emp_cursor INTO emp_record; 
    EXIT WHEN v_emp_cursor%NOTFOUND; 
    END LOOP; 

    -- Close cursor: 
    CLOSE v_emp_cursor; 
END; 


declare 
    v_rc sys_refcursor; 
begin 
    v_rc := get_dept_emps(10); -- This returns an open cursor 
    dbms_output.put_line('Rows: '||v_rc%ROWCOUNT); 
    close v_rc; 
end; 

查找更多的示例在這裏。 http://forums.oracle.com/forums/thread.jspa?threadID=886365&tstart=0

+0

謝謝,但是這個建議的解決方案在我的摘要(沒有打印語句)和第5點中違反了第4點。這兩個都是必需的,因爲我使用了一個自定義的GUI工具來查看我的結果(認爲它是一個非常基本的SqlDeveloper應用程序)。 – 2010-04-05 20:16:38

0

蟾蜍執行腳本時下面你將被提示輸入v_result的類型。從類型選擇列表中選擇光標,然後將結果顯示在Toad的數據網格(excel電子表格,如結果)中。也就是說,當使用遊標作爲結果時,您應該總是編寫兩個程序(客戶端和服務器)。在這種情況下,'TOAD'將成爲客戶。

DECLARE 
    v_result  sys_refcursor; 
    v_dynamic_sql VARCHAR2 (4000); 
BEGIN 
    v_dynamic_sql := 'SELECT * FROM user_objects where ' || ' 1 = 1'; 

    OPEN :v_result FOR (v_dynamic_sql); 
END; 

在Oracle的SQL Developer中也可能有類似的機制來提示綁定。

+0

有一個類似的機制,正如我在我的問題中指出的一個鏈接,但是這個建議違反了我總結中的第5點(沒有特殊的SqlDeveloper功能 - 代碼塊需要完全獨立)。 – 2010-04-05 20:18:10