#oracle #plsql #procedure
#Oracle #plsql #процедура
Вопрос:
Ранее у меня было аналогичное требование, но теперь мне дали четкий подход, который необходимо реализовать.
Мне нужно написать процедуру (желательно) / функцию, которая на основе app_id, переданного в качестве параметра, изменяла бы заголовки столбцов на соответствующие значения, отображаемые в динамическом представлении.
Таблица с заголовками столбцов — DATA_HEADER .
Таблица со значением — DATA_VALUE .
Заголовки и значения столбцов должны быть развернуты по порядку.
Обе таблицы имеют общий идентификатор app_id. Таким образом, для app_id=1 метки из DATA_HEADER будут использоваться против значений в DATA_VALUE . Однако значения изменяются только на основе PID, поэтому они останутся постоянными, будут меняться только заголовки для каждого идентификатора приложения.
Когда app_id передается в proc / funct, ожидаемое представление должно быть:
Таким образом, в основном заголовки меняются для каждого app_id, а максимальное количество заголовков столбцов будет равно 20. Таким образом, номер или имя должны меняться, как в таблице DATA_HEADER. Значения однозначно идентифицируются на основе pid.
Порядок заголовков столбцов будет соответствовать столбцу seq в DATA_HEADER. Аналогично порядок значений будет соответствовать столбцу seq в значении данных, поэтому последовательность должна соблюдаться и поворачиваться соответствующим образом.
PS Приложение в конце — Oracle apex, откуда будет вызываться процедура / функция.
Версия Oracle: 12.1
Комментарии:
1. Вам трудно понять, как должен выглядеть сгенерированный код или как скомпилировать сгенерированный код? Что вы пробовали до сих пор?
2. Я пробовал выполнять поворот с использованием динамического sql, сводного xml, но ничто из этого не помогает форматировать данные. т.Е. Динамически изменять заголовки столбцов, никакие решения не работали, поэтому мне предложили попробовать этот подход. Я могу написать процедуру, но я не могу понять, как создавать динамические представления с помощью процедуры с изменением заголовков внутри процедуры.
3. Вы можете добавить весь свой код в VARCHAR2 или CLOB, а затем скомпилировать его с помощью
EXECUTE IMMEDIATE
. (пример:BEGIN EXECUTE IMMEDIATE 'CREATE VIEW v AS SELECT dummy FROM dual'; END;
)
Ответ №1:
Один из вариантов — создать функцию, подобную приведенной ниже, затем вызвать курсор из SQLPlus, SQLcl или любого другого используемого вами инструмента. Если вы используете Java или APEX, вы можете использовать refcursor или даже просто значение в l_sql
, чтобы получить нужный вам оператор select .
Функция
CREATE OR REPLACE FUNCTION get_data (p_app_id data_header.app_id%type)
RETURN SYS_REFCURSOR
IS
TYPE headers_t IS TABLE OF data_header.label%TYPE;
l_headers headers_t;
l_cur SYS_REFCURSOR;
l_sql VARCHAR2 (32767);
BEGIN
SELECT label
BULK COLLECT INTO l_headers
FROM data_header
WHERE app_id = p_app_id
ORDER BY seq;
l_sql := 'select * FROM (SELECT *
FROM data_value
WHERE app_id = ' || p_app_id || ')
PIVOT (MIN (VALUE) FOR seq IN (';
FOR i IN 1 .. l_headers.COUNT
LOOP
l_sql :=
l_sql
|| i
|| ' as "'
|| l_headers (i)
|| CASE WHEN i < l_headers.COUNT THEN '", ' ELSE '"' END;
END LOOP;
l_sql := l_sql || '))';
OPEN l_cur FOR l_sql;
RETURN l_cur;
END;
/
SQLPlus или SQLcl
Вы можете использовать курсор следующим образом
SQL> variable l_cursor refcursor;
SQL> begin
2 :l_cursor := get_data(1);
3 end;
4 /
PL/SQL procedure successfully completed.
SQL> print l_cursor;
Обновить
Поскольку ваш конечный пользовательский интерфейс — APEX, этот запрос может быть создан для работы в APEX. Возвращая значение в l_sql, вы можете создать классический отчет, используя этот запрос. Я создал демонстрационное приложение на apex.oracle.com показывая, что это возможно.
Комментарии:
1. Спасибо, можно ли это вызвать, если конечным приложением является oracle apex? Или нам нужно было бы обернуть это во что-то вроде конвейерной функции?
2. Кроме того, PIVOT (MIN (ЗНАЧЕНИЕ) ДЛЯ seq В (‘; —> Это PIVOT (MIN (ЗНАЧЕНИЕ) ДЛЯ seq В (‘;’); ??
3. Динамический запрос в l_sql можно использовать в APEX для создания классического отчета. Я обновил сообщение ссылкой на образец приложения, которое я создал.