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

Подробнее:
Есть функция, которая по заданному параметру выбирает и группирует данные из БД, затем делает 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
Построение Dynamic Pivot Table
    #39748868
Фотография -2-
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
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
Построение Dynamic Pivot Table
    #39748883
zhdanovmyu
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
-2-,
к сожалению, постановка задачи подразумевает именно выполнение обычного select-а.
Интерфейс системы, в которой должна запускаться эта функция, не позволяет использовать анонимные блоки.
...
Рейтинг: 0 / 0
Построение Dynamic Pivot Table
    #39748887
Фотография Elic
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
zhdanovmyuк сожалению, постановка задачи подразумевает именно выполнение обычного select-а.Постановщик не знаком с принципиальными ограничениями.
...
Рейтинг: 0 / 0
Построение Dynamic Pivot Table
    #39748993
rpovarov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Гуглить в направлении "CREATE FUNCTION ... RETURN ANYDATASET PIPELINED USING ...;", "ODCITableDescribe", "ODCITablePrepare" и т.п.
Практическая реализация (парсинг Excel файла) есть тут: https://github.com/mbleron/ExcelTable
...
Рейтинг: 0 / 0
Построение Dynamic Pivot Table
    #39748998
rpovarov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
...
Рейтинг: 0 / 0
Построение Dynamic Pivot Table
    #39749004
MazoHist
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Далеко ходить не надо: 21730259
...
Рейтинг: 0 / 0
7 сообщений из 7, страница 1 из 1
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Построение Dynamic Pivot Table
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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