【问题标题】:PL/SQL Add Multiple Columns to Query with Single FunctionPL/SQL 添加多列以使用单个函数进行查询
【发布时间】:2017-08-10 22:41:36
【问题描述】:

有没有办法在 PL/SQL 中完成类似的事情...

select a.col1, a.col2, a.col3, myFunc(a.id) from myTable a;

结果超过 4 列?所以基本上,有没有办法让函数返回或返回多个列?所需的数字是已知的并且一成不变,它是 3。所以这个查询将返回 6 列。我知道我可以分别调用myFunc() 3 次,但处理量会增加三倍。

我一直在玩管道函数,但似乎它们不能用于执行此操作。

Oracle 数据库 11g 企业版 11.2.0.2.0 - 64 位

生产 PL/SQL 版本 11.2.0.2.0 - 生产

谢谢!

【问题讨论】:

  • 如果函数要返回的元组的大小是“已知且一成不变”,那么为什么不编写查询以包括三列呢?
  • @Kirby 函数返回的列来自其他表。连接可能有效,但它会是一个冗长而复杂的连接,需要在许多不同的查询中使用,所以我不想继续重写该连接。那么我说,制作一个视图并让所有查询都基于该视图,然后我就不必继续重写该连接了。这可能行得通,但目前代码在一个函数中,而且很复杂,我不确定这一切是否都可以在 SQL 中完成。现在正在经历这一切。

标签: sql oracle plsql


【解决方案1】:

以下是在各种 Oracle 版本中执行此操作的方法。我只使用DBA_OBJECTS 代替您的真实桌子。

CREATE OR REPLACE TYPE my_func_rec IS OBJECT
(
  mf_col1 NUMBER,
  mf_col2 NUMBER,
  mf_col3 NUMBER
);

CREATE OR REPLACE TYPE my_func_tab IS TABLE OF my_func_rec;

CREATE OR REPLACE FUNCTION my_func (id NUMBER)
  RETURN my_func_tab IS
  l_result   my_func_tab;
BEGIN
  SELECT my_func_rec (id + 100, id + 101, id + 102)
  BULK   COLLECT INTO l_result
  FROM   DUAL;

  RETURN l_result;
END my_func;

12c

在 12c 中,使用 CROSS APPLY 非常简单。

SELECT object_id,
       object_type,
       status,
       mf_col1,
       mf_col2,
       mf_col3
FROM   dba_objects o
       CROSS APPLY (SELECT mf_col1,
                           mf_col2,
                           mf_col3
                    FROM   TABLE (my_func (o.object_id)) odet);

11g

在 11g 中,您无权访问 CROSS APPLY,因此您需要选择函数结果作为对象,然后选择 TREAT 作为对象以访问各个字段。

SELECT object_id,
       object_type,
       status,
       TREAT (val AS my_func_rec).mf_col1,
       TREAT (val AS my_func_rec).mf_col2,
       TREAT (val AS my_func_rec).mf_col3
FROM   (SELECT object_id,
               object_type,
               status,
               (SELECT my_func_rec (mf_col1, mf_col2, mf_col3)
                FROM   TABLE (my_func (o.object_id)) mf)
                 val
        FROM   dba_objects o)  

注意:我在 12c 答案之后创建了 11g 答案。 11g 的答案可以通过让my_func 返回my_func_rec 而不是my_func_tab 来进一步简化。在这种情况下,它会简化为:

SELECT object_id,
       object_type,
       status,
       TREAT (val AS my_func_rec).mf_col1,
       TREAT (val AS my_func_rec).mf_col2,
       TREAT (val AS my_func_rec).mf_col3
FROM   (SELECT object_id,
               object_type,
               status,
               my_func (o.object_id) val
        FROM   dba_objects o)

【讨论】:

  • 你只能保留完整的答案部分作为答案,因为当我从头开始看时,前面的部分有点混乱。
  • 你说得对,@XING。为了(希望)更清晰,我已经对其进行了重新组织。谢谢。
【解决方案2】:

一个非常简单的插图。希望对您有所帮助。

--The best way here is to make a table type function
--as mentioned below


--Create object type
CREATE OR REPLACE TYPE OBJ_DUM
IS
  OBJECT
  (
    COL1 NUMBER,
    COL2 NUMBER,
    COL3 VARCHAR2(100) );
    /

--Create table type    
CREATE OR REPLACE TYPE TAB_DUM
IS
  TABLE OF OBJ_DUM;
  /


--Create dummy function. This canbe a pipelined function also 
CREATE OR REPLACE
FUNCTION SO_DUM
  RETURN TAB_DUM
AS
  lv_tab tab_dum:=tab_dum(NULL,NULL,NULL);
BEGIN
  SELECT obj_dum(level,level+1,'AVRAJIT+'
    ||LEVEL) BULK COLLECT
  INTO lv_tab
  FROM DUAL
    CONNECT BY LEVEL < 2;
  RETURN lv_tab;
END;
/


--To check the output
SELECT TAB.*,OBJ.* FROM USER_OBJECTS OBJ,TABLE(SO_DUM) TAB;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-10-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-12-21
    • 2014-05-17
    • 1970-01-01
    相关资源
    最近更新 更多