Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Построение Dynamic Pivot Table / 7 сообщений из 7, страница 1 из 1
17.12.2018, 12:34
    #39748865
zhdanovmyu
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Построение Dynamic Pivot Table
Доброго времени суток всем.
Подскажите, как вывести данные из функции, если она возвращает курсор?

Подробнее:
Есть функция, которая по заданному параметру выбирает и группирует данные из БД, затем делает pivot полученной структуры (с помощью dynamic sql). Фактически, это немного изменённая функция dynamic pivot Тома Кайта с ресурса "Ask TOM". Количество строк в выборке перед pivot может быть разным, соответственно, и количество столбцов в итоговой таблице тоже.
При попытке выбрать данные простым select * from function(@param) возвращается ORA-22905: cannot access rows from non-nested table item. Объявление типа и использование конструкции TABLE(CAST(...)) также не помогает, т.к. заранее не знаю структуру типа.

Сам пакет с функциями:

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
create or replace package PKG_PIVOT is

 function pivot_sql (
                     p_max_cols_query in varchar2 default null
                    , p_query in varchar2
                    , p_anchor in varchar2_table
                    , p_pivot in varchar2_table
                    , p_pivot_head_sql in varchar2_table default varchar2_table()
                    ) 
 return varchar2;
 
 function pivot_ref (
                        p_max_cols_query in varchar2 default null
                     , p_query in varchar2
                     , p_anchor in varchar2_table
                     , p_pivot in varchar2_table
                     , p_pivot_name in varchar2_table default varchar2_table()
                     )
 return sys_refcursor;

end PKG_PIVOT;


create or replace package body PKG_PIVOT is
/**
* Function returning query
*/
 function pivot_sql (
                     p_max_cols_query in varchar2 default null
                    , p_query in varchar2
                    , p_anchor in varchar2_table
                    , p_pivot in varchar2_table
                    , p_pivot_head_sql in varchar2_table
                    ) return varchar2
                    is
    l_max_cols number;
    l_query varchar2(5000);
    l_pivot_name varchar2_table:=varchar2_table();
    k integer;
    c1 sys_refcursor;
    v varchar2(500);
 begin
    -- Получаем кол-во столбцов
    if (p_max_cols_query is not null) then
     execute immediate p_max_cols_query
        into l_max_cols;
    else
     raise_application_error (-20001, 'Cannot figure out max cols');
    end if;

    -- Собираем по кускам необходимый нам запрос
    l_query := 'select ';

    for i in 1 .. p_anchor.count loop
     l_query := l_query || p_anchor (i) || ',';
    end loop;
    --Получаем названия колонок
    k:=1;
    if p_pivot_head_sql.count=p_pivot.count
     then
         for j in 1 .. p_pivot.count loop
            open c1 for p_pivot_head_sql(j);
            loop
             fetch c1 into v;
             l_pivot_name.extend(1);
             l_pivot_name(k):=v;
             EXIT WHEN c1%NOTFOUND;
             k:=k+1;
            end loop;
         end loop;
    end if;
     
    -- Добавляем колонки с полученными названиями
    -- в виде "max(decode(rn,1,C{X+1},null)) c_name+1_1"
    for i in 1 .. l_max_cols loop
     for j in 1 .. p_pivot.count loop
        l_query := l_query || 'sum(decode(rn,' || i || ',' || p_pivot (j) || ',0)) '
                  ||'"' ||l_pivot_name ((j-1)*l_max_cols+i) ||'"'|| ',';
     end loop;
    end loop;

    -- Вставляем исходный запрос
    l_query := rtrim (l_query, ',') || ' from ( ' || p_query || ') group by ';

    -- Группируем по колонкам
    for i in 1 .. p_anchor.count loop
     l_query := l_query || p_anchor (i) || ',';
    end loop;

    l_query := rtrim (l_query, ',');

    -- Возвращаем готовый SQL запрос
    return l_query;
 end;
 
/**
* Функция возвращающая курсор на выполненный запрос
*/
 function pivot_ref (
                     p_max_cols_query in varchar2 default null
                    , p_query in varchar2
                    , p_anchor in varchar2_table
                    , p_pivot in varchar2_table
                    , p_pivot_name in varchar2_table
                    ) return sys_refcursor
                    is
    p_cursor sys_refcursor;
 begin
    execute immediate 'alter session set cursor_sharing=force';
    open p_cursor for pkg_pivot.pivot_sql (
                     p_max_cols_query
                    , p_query
                    , p_anchor
                    , p_pivot
                    , p_pivot_name
                    );
    execute immediate 'alter session set cursor_sharing=exact';
    return p_cursor;
 end;
end PKG_PIVOT;
...
Рейтинг: 0 / 0
17.12.2018, 12:39
    #39748868
-2-
-2-
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Построение Dynamic Pivot Table
zhdanovmyuкак вывести данные из функции, если она возвращает курсор?
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
SQL> var rc refcursor
SQL> exec open :rc for select 123 a, sysdate b from dual

PL/SQL procedure successfully completed.

SQL> print rc

         A B                  
---------- -------------------
       123 2018-12-17 12:37:36
...
Рейтинг: 0 / 0
17.12.2018, 13:00
    #39748883
zhdanovmyu
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Построение Dynamic Pivot Table
-2-,
к сожалению, постановка задачи подразумевает именно выполнение обычного select-а.
Интерфейс системы, в которой должна запускаться эта функция, не позволяет использовать анонимные блоки.
...
Рейтинг: 0 / 0
17.12.2018, 13:04
    #39748887
Elic
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Построение Dynamic Pivot Table
zhdanovmyuк сожалению, постановка задачи подразумевает именно выполнение обычного select-а.Постановщик не знаком с принципиальными ограничениями.
...
Рейтинг: 0 / 0
17.12.2018, 15:13
    #39748993
rpovarov
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Построение Dynamic Pivot Table
Гуглить в направлении "CREATE FUNCTION ... RETURN ANYDATASET PIPELINED USING ...;", "ODCITableDescribe", "ODCITablePrepare" и т.п.
Практическая реализация (парсинг Excel файла) есть тут: https://github.com/mbleron/ExcelTable
...
Рейтинг: 0 / 0
17.12.2018, 15:17
    #39748998
rpovarov
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Построение Dynamic Pivot Table
...
Рейтинг: 0 / 0
17.12.2018, 15:27
    #39749004
MazoHist
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Построение Dynamic Pivot Table
Далеко ходить не надо: 21730259
...
Рейтинг: 0 / 0
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Построение Dynamic Pivot Table / 7 сообщений из 7, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]