2010-04-05 155 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