Oracle PL/SQL 过程/函数来创建包含列的视图
Posted
技术标签:
【中文标题】Oracle PL/SQL 过程/函数来创建包含列的视图【英文标题】:Oracle PL/SQL Procedure/function to create view with columns 【发布时间】:2020-11-24 09:42:24 【问题描述】:我之前有类似的要求,但现在我得到了一个需要实施的明确方法。
我需要编写一个过程(最好)/函数,它会根据作为参数传递的 app_id,更改在动态视图中旋转的相应值的列标题。
具有列标题的表是 DATA_HEADER。
值为 DATA_VALUE 的表。
列标题和值需要按顺序旋转。
两个表都有共同的 app_id。因此对于 app_id=1,来自 DATA_HEADER 的标签将用于 DATA_VALUE 中的值。但是,这些值仅根据 PID 变化,因此它们将保持不变,只有标头会根据应用 ID 变化。
当 app_id 在 proc/funct 中传递时,预期的视图应该是:
所以基本上,每个 app_id 的标题都会发生变化,列标题的最大数量为 20。因此数字或名称应与表 DATA_HEADER 中的不同。 这些值是根据 pid 唯一标识的。
列标题的顺序将按照 DATA_HEADER 中的 seq 列。 同样,值的顺序将按照数据值中的 seq 列进行,因此必须遵循该顺序并相应地进行旋转。
附:最后的应用程序是调用 proc/function 的 Oracle apex。
Oracle 版本:12.1
【问题讨论】:
您是否为生成的代码应该是什么样子或如何编译生成的代码而苦恼?到目前为止,您尝试过什么? 我尝试过使用动态 sql、pivot xml 进行数据透视,但这些都不能帮助格式化数据。即动态更改列标题,没有解决方案有效,因此建议我尝试这种方法。我可以编写一个程序,但我无法理解如何通过 proc 创建动态视图,并在 proc 内更改标题。 您可以将所有代码附加到 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;
更新
由于您的最终 UI 是 APEX,因此可以构建此查询以在 APEX 中工作。通过返回 l_sql 中的值,您可以使用该查询创建经典报告。我已经建立了一个demo application on apex.oracle.com 表明它是可能的。
【讨论】:
谢谢,如果最后的应用是oracle apex,可以调用吗?或者我们需要把它包装成类似流水线函数的东西? 还有,PIVOT (MIN (VALUE) FOR seq IN ('; --> 这是 PIVOT (MIN (VALUE) FOR seq IN (';'); ?? l_sql中的动态查询可以在APEX中使用,生成经典报表。我已经用我构建的示例应用程序的链接更新了帖子。以上是关于Oracle PL/SQL 过程/函数来创建包含列的视图的主要内容,如果未能解决你的问题,请参考以下文章
ORACLE PL/SQL 在查询 3 列信息时出现存储过程错误
在咨询3列信息时,ORACLE PL / SQL错误与存储过程有关