简体   繁体   English

Oracle 12c:我可以从同时获取和返回表的WITH子句中调用函数吗?

[英]Oracle 12c: Can I invoke a function from a WITH clause which both takes and returns a table?

I want to write a PL/SQL function which can be used in a variety of queries, particular the subqueries of a WITH clause. 我想编写一个PL / SQL函数,该函数可用于各种查询,尤其是WITH子句的子查询。 The tricky part is that I want the function to both receive and return a one-column TABLE (or CURSOR) of information. 棘手的部分是我希望函数同时接收返回信息的单列表(或CURSOR)。

Details: imagine that this function just sorts a list of employee IDs according to some very complicated criteria. 详细信息:假设此功能只是根据一些非常复杂的标准对员工ID列表进行排序。 We'd have this: 我们有这个:

  • My function is called SORT_EMPLOYEES 我的函数叫做SORT_EMPLOYEES
  • My function takes a 1-column table of employee IDs (emp_id) as input. 我的函数将员工ID(emp_id)的1列表作为输入。
  • This input type is probably a TABLE type EMP_T_TYPE. 此输入类型可能是TABLE类型EMP_T_TYPE。
  • This return type is probably also a TABLE type EMP_T_TYPE. 此返回类型也可能是TABLE类型的EMP_T_TYPE。

So far so good, I hope. 希望到目前为止一切顺利。

Now, I think that I can use the output of the function with the TABLE operator pretty much anywhere; 现在,我认为几乎可以在任何地方使用TABLE运算符使用函数的输出了; eg: 例如:

    WITH
    wanted_emps AS (...),  -- find employees we want, as table of emp_id
    ranked_emps AS (
        SELECT rownum() as rank, emp_id 
        FROM TABLE(SORT_EMPLOYEES(...???...))
    ),
    ...

The problem is: how can I get the list of employees from 'wanted_emps' and make it the input of SORT_EMPLOYEES? 问题是:如何从“ wanted_emps”获取雇员列表,并将其作为SORT_EMPLOYEES的输入? What goes in the "...???..." above? 上面的“ ... ??? ...”中有什么内容? Is this even possible? 这有可能吗?

Please note that I want this to be used from plain SQL, especially from subqueries of WITH clauses as shown above -- not from PL/SQL. 请注意 ,我希望在普通SQL中使用它,尤其是在如上所述的WITH子句的子查询中使用-而不是PL / SQL。 Thanks! 谢谢!

Here is an example of how to COLLECT values into a collection which can then be passed to a FUNCTION that returns another collection: 这是一个如何将值收集到一个集合中的示例,然后可以COLLECT集合传递给返回另一个集合的FUNCTION

Oracle Setup : Oracle安装程序

CREATE TYPE numbers_table AS TABLE OF NUMBER;

CREATE TABLE test_data ( grp, value ) AS
  SELECT 1, 1 FROM DUAL UNION ALL
  SELECT 1, 2 FROM DUAL UNION ALL
  SELECT 1, 3 FROM DUAL UNION ALL
  SELECT 2, 4 FROM DUAL UNION ALL
  SELECT 2, 5 FROM DUAL UNION ALL
  SELECT 3, 6 FROM DUAL;

Query : 查询

WITH FUNCTION square( i_numbers IN numbers_table ) RETURN numbers_table
IS
  p_numbers numbers_table := numbers_table();
  p_count   PLS_INTEGER;
BEGIN
  IF i_numbers IS NULL THEN
    p_count := 0;
  ELSE
    p_count := i_numbers.COUNT;
  END IF;
  p_numbers.EXTEND( p_count );
  FOR i IN 1 .. p_count LOOP
    p_numbers(i) := i_numbers(i) * i_numbers(i);
  END LOOP;
  RETURN p_numbers;
END;
collected_rows ( grp, grouped_values ) AS (
  SELECT grp,
         CAST(
           COLLECT( value ORDER BY value )
           AS numbers_table
         )
  FROM   test_data
  GROUP BY grp
)
SELECT c.grp,
       t.COLUMN_VALUE AS squared_value
FROM   collected_rows c
       CROSS JOIN
       TABLE( square( c.grouped_values ) ) t;

Output : 输出

\nGRP | 玻璃钢| SQUARED_VALUE SQUARED_VALUE\n--: | -:| ------------: ------------:\n  1 | 1 | 1 1个\n  1 | 1 | 4 4\n  1 | 1 | 9 9\n  2 | 2 | 16 16\n  2 | 2 | 25 25\n  3 | 3 | 36 36\n

db<>fiddle here db <> 在这里拨弄

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM