从Oracle函数返回完全动态的表


8

我想编写一个带有两个IN参数的函数,其中第一个是a varchar,第二个是a的列表varchars。基于这些,我想返回一个具有不同列数和类型名称的表varchar

据我所知,我必须始终创建一个对象/记录及其表类型。这意味着我的想法行不通吗?基本目标是将系统命令输出作为表传递回被调用方。

编辑:更多的任务。我想发出一个OS命令,使用输出并将其作为表返回。OS命令的输出将是CSV格式的数据。在执行时,我不知道要返回的行数,而仅知道作为第二个arg传递的列数。我想使用的Java与动态STRUCTARRAY包含它们。尽管我更喜欢前一种方法。

它看起来应该像这样:

create function(clob query, list of varchars cols) returns table
begin
  execute system command(query, cols);
  examine sysout from command;
  return tabular data from syscmd as table;
end

评论不作进一步讨论;此对话已转移至聊天
保罗·怀特9

Answers:


1

尽管很复杂,但是有可能编写返回变量结构流水线表函数。您的管道表函数可以采用两个参数,并使用Oracle Data Cartridge接口和AnyDataSet类型的魔力在运行时返回动态结构。然后,您可以在后续的SQL语句中使用它,就像它是一个表一样,即

SELECT *
  FROM TABLE( your_pipelined_function( p_1, p_2 ));

还有更多参考文献讨论相同的示例实现


0

我认为您最好的方法是放弃发送回动态表的尝试(尽管我想您也许可以创建临时表并将其返回给它,但是我不确定在这里)。

我在这里的首选方法是以更灵活的格式(例如XML文档等)生成结果并将其返回。这为您提供了所需的灵活性,而不必在功能扫描后确定列。


克里斯,您好,谢谢您的回答。我已经放弃了动态表,因为它根本不可能。XML太冗长,但却是个好主意。我的主要问题是我需要调用静态Java函数来查询lucene索引。这意味着我需要每次打开和关闭索引。这是非常无效的。我求助于具有JSON和XML输出的REST服务。
Michael-O

0

您可以创建一个tmp视图,并动态替换该视图。

create or replace view tmp_view as select 1 x from dual;
/
create or replace package pkg_input_sql is
  cursor my_cursor is select * from tmp_view;

  my_rec_type my_cursor%rowtype;
  type my_tab_type is table of my_cursor%rowtype;

  function get_cursor(p_sqlstr varchar2) return sys_refcursor;
  function get_table return my_tab_type
    pipelined;

end pkg_input_sql;
/
create or replace package body pkg_input_sql is

  function get_cursor(p_sqlstr varchar2) return sys_refcursor as
    my_cursor sys_refcursor;
  begin
    open my_cursor for p_sqlstr;
    return my_cursor;
  end get_cursor;

  function get_table return my_tab_type
    pipelined is
    my_tab    my_tab_type;
    i         pls_integer;
    my_cursor sys_refcursor;
  begin
    my_cursor := get_cursor('select * from tmp_view');
    fetch my_cursor bulk collect
      into my_tab;
    for i in 1 .. my_tab.count loop
      pipe row(my_tab(i));
    end loop;
  end;

begin
  null;
end pkg_input_sql;
/

create or replace procedure create_tmp_view(p_sqlstr varchar2) is
begin
  execute immediate 'create or replace view tmp_view as ' || p_sqlstr;
  dbms_utility.exec_ddl_statement('alter package pkg_get_sql compile package');
  dbms_session.reset_package; -- to avoid ora-04068
end create_tmp_view;

执行结果:

在此处输入图片说明


-1

一种解决方案是根据Lucene输出创建一个外部表。您可以轻松更改外部表定义(并将其指向多个文件)。

因此,您将拥有:

function l_query(clob query, list of varchars cols) returns table_name
begin 
execute system command(query, cols); 
#hopefully we know the output filename
create a new external table mapping the output;
end

会工作的!文件的定义是已知的,我们可以动态地创建一个外部表。
Ohadi 2012年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.