Возврат полностью динамической таблицы из функции Oracle

8

Я хотел бы написать функцию с двумя INпараметрами, где первый - varcharэто список, а второй - список varchars. Исходя из этого, я хочу вернуть таблицу с различными значениями столбцов и именами типов varchar.

Насколько я видел, я всегда должен создавать объект / запись и тип таблицы. Это значит, что моя идея не сработает? Основная цель - передать выходные данные системной команды вызываемой стороне в виде таблицы.

Изменить: больше на задаче. Я хочу выполнить команду ОС, использовать вывод и вернуть его обратно в виде таблицы. Вывод команды ОС будет представлять собой данные в формате CSV. Во время выполнения я не знаю количество строк, которые должны быть возвращены, а только количество столбцов, которое передается как второй аргумент. Я думал об использовании Java с динамическими STRUCTи ARRAYсодержащими их. Хотя я бы предпочел первый подход.

Это должно выглядеть так:

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
Michael-O
источник
Комментарии не для расширенного обсуждения; этот разговор был перенесен в чат .
Пол Уайт 9

Ответы:

1

Можно, хотя и довольно сложно, написать конвейерную табличную функцию, которая возвращает переменную структуру . Ваша конвейерная табличная функция может принимать два аргумента и использовать интерфейс Oracle Data Cartridge и магию типа AnyDataSet для возврата динамической структуры во время выполнения. Затем вы можете использовать это в последующих операторах SQL, как если бы это была таблица, т.е.

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

Еще пара ссылок, которые обсуждают тот же пример реализации

Джастин Кейв
источник
0

Я думаю, что ваш лучший подход - отказаться от попытки отправить динамическую таблицу обратно (хотя я полагаю, что вы могли бы создать временную таблицу и вернуть к ней рекурсор, но я здесь не уверен).

Мой предпочтительный подход заключается в том, чтобы генерировать результаты в более гибком формате, что-то вроде XML-документа или тому подобное, и возвращать его. Это дает вам необходимую гибкость без необходимости определять столбцы после сканирования функции.

Крис Траверс
источник
Привет Крис, спасибо за ответ. Я уже отказался от динамической таблицы, потому что это просто невозможно. XML слишком многословен, но хорошая идея. Моя главная проблема заключается в том, что мне нужно вызвать статическую функцию Java для запроса индекса lucene. Это будет означать, что мне нужно каждый раз открывать и закрывать индекс. Это очень неэффективно. Я прибег к REST-сервису с выводом JSON и XML.
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
источник
Это будет работать! Определение файла известно, и мы можем динамически создать внешнюю таблицу.
Охади