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错误与存储过程有关

oracle pl/sql 包

ORACLE 存储函数

oracle 存储过程详细介绍(创建,删除存储过程,参数传递等)

PL/SQL学习笔记_03_存储函数与存储过程