Как определить функцию PL SQL с динамическими типами возврата в Oracle? - PullRequest
2 голосов
/ 11 мая 2011

У меня есть набор таблиц с разными типами данных для столбцов, и мне нужно консолидировать способ получения данных. Я думал, что использование функции было бы хорошей идеей, но я не знаю, как определить одну функцию, имеющую разные типы возврата.

Например, как определить эту функцию, чтобы можно было использовать разные определения для типа таблицы.

CREATE OR REPLACE FUNCTION retrieve_info(field_id in integer)
RETURN pintegertypetable -- <-- how to change this to return a more generic record built dynamically in the code below?
AS
  r pintegertypetable := pintegertypetable ();
BEGIN
  r.extend;
  r(i) := pintegertypetable (someinteger);
  return r;
END;

Это возможно? Есть ли лучший способ справиться с этой проблемой: разные столбцы изначально хранятся во многих унаследованных таблицах, и учитывая, что каждый столбец имеет разные типы данных, и таким образом мы можем получить самую свежую информацию, сохраняющую исходные типы данных, без жесткого представления хранить все в varchar2 и снова приводить в код клиента?

Ответы [ 3 ]

6 голосов
/ 11 мая 2011

Вы можете реализовать это, используя слабо типизированный Ref Refsor в качестве возвращаемого типа.Это особенно легко реализовать из клиентского интерфейса с использованием JDBC, так как возвращаемый тип курсора может проходить точно так же, как и любой результат запроса, и метаданные можно запрашивать из ResultSet.getMetaData ().Вот пример:

CREATE OR REPLACE PROCEDURE retrieve_info(field_id in integer, p_cursor in out sys_refcursor)
AS
BEGIN
  open p_cursor for 'select * from emp';
END;

Запрос в кавычках может быть любым, возвращающим любой тип, для любого количества столбцов.

1 голос
/ 11 мая 2011

Если вы заинтересованы в приведении отдельных столбцов к строкам, проще всего написать пакет с перегруженными функциями.Каждая функция имеет одинаковое имя, меняется только сигнатура входных параметров:

SQL> create or replace package str_util
  2  as
  3      function s (p in varchar2) return varchar2;
  4      function s (p in number) return varchar2;
  5      function s (p in date, fmt in varchar2 := 'dd-mon-yyyy') return varchar2;
  6  end;
  7  /

Package created.

SQL>

Это, очевидно, упрощенная реализация.Для производства вам может потребоваться обработка ошибок, маски числового формата, дополнительные типы данных и т. П.* В этой версии запроса я вызываю упакованную функцию и возвращаю три строки:

SQL> select dump(str_util.s(id)) id_is_number
  2         , dump(str_util.s(col2)) col2_is_varchar
  3         , dump(str_util.s(col3)) col3_is_date
  4  from big_table
  5  where rownum = 1
  6  /

ID_IS_NUMBER
------------------------------------------------------------------
COL2_IS_VARCHAR
------------------------------------------------------------------
COL3_IS_DATE
------------------------------------------------------------------
Typ=1 Len=3: 52,51,54
Typ=1 Len=11: 73,95,65,82,71,85,77,69,78,84,49
Typ=1 Len=11: 49,53,45,111,99,116,45,50,48,48,55


SQL>
1 голос
/ 11 мая 2011

Используя ответ Datajam Ltd, это может быть полезно для кого-то еще:

drop table xxx1;
drop table xxx2;
drop table xxx3;
drop table xxx4;

create table xxx1(val integer);
create table xxx2(val date);
create table xxx3(val number);
create table xxx4(val varchar2(100));

insert into xxx1 (val) select rownum from all_objects where rownum <= 1;
insert into xxx2 (val) select sysdate+rownum from all_objects where rownum <= 2;
insert into xxx3 (val) select 12.345+rownum from all_objects where rownum <= 3;
insert into xxx4 (val) select 'test'||rownum from all_objects where rownum <= 4;

CREATE OR REPLACE PROCEDURE retrieve_info(p_cursor in out sys_refcursor, tabname in varchar2) 
AS 
BEGIN 
    open p_cursor for 'select val from ' || tabname; 
END; 
/



-- CLIENT CODE IN PLSQL:

drop table logtable;
create table logtable(x varchar2(1000));

declare
     v_rc sys_refcursor;
     b varchar2(1000);
begin
     retrieve_info(v_rc, 'xxx2'); -- here you can parameterize your call     
     loop
          fetch v_rc into b;
              exit when v_rc%notfound;
              dbms_output.put_line(b);
              insert into logtable(x) values(b);
      end loop;
end;
/

select * from logtable;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...