Oracle PL / SQL:函数游标

时间:2017-01-16 15:45:31

标签: sql oracle plsql

我收到错误:

  

PLS-00231:功能' GET_NUM'可能不会在SQL中使用

执行以下代码时;

CREATE OR REPLACE PACKAGE BODY TESTJNSABC IS

  -- FUNCTION IMPLEMENTATIONS
  FUNCTION get_num(num IN NUMBER) 
    RETURN SYS_REFCURSOR AS
    my_cursor SYS_REFCURSOR;
  BEGIN
    --
    OPEN my_cursor FOR 
    WITH ntable AS (
         SELECT 1 ID, 111 AGT, 'ABC' DESCRIP FROM DUAL
         UNION ALL
         SELECT 2 ID, 222 AGT, 'ABC' DESCRIP FROM DUAL
         UNION ALL
         SELECT 1 ID, 333 AGT, 'ABC' DESCRIP FROM DUAL
    )
    SELECT AGT FROM ntable WHERE ID = num;
    RETURN my_cursor;

  END;

  -- PROCEDURE IMPLEMENTATIONS 
  PROCEDURE testingabc AS

    BEGIN
      WITH xtable AS (
         SELECT 111 AGT, 'A' DESCRIP FROM DUAL
         UNION ALL
         SELECT 222 AGT, 'B' DESCRIP FROM DUAL
         UNION ALL
         SELECT 333 AGT, 'C' DESCRIP FROM DUAL
     )
      SELECT DESCRIP FROM xtable WHERE COD_AGT IN get_num(1);


    END testingabc;

END TESTJNSABC;

即使我将该函数称为TESTJNSABC.get_num(1),我仍然会收到相同的错误。 --update。所以在现实生活中我想从一个WHERE CLAUSE中调用一个函数;该函数应返回一组NUMBER值(这就是我使用IN子句的原因)。

3 个答案:

答案 0 :(得分:1)

  

那么就可以在Procedure和。上创建一个变量   将函数值赋给变量?我们说

如果这是正确的方式,那么问题是否可能不是问题。当然,你可以按照自己的方式去做,但正如专家建议的那样,这不是正确有效的方式。看看你怎么做。 PS:未经测试。

CREATE OR REPLACE PACKAGE BODY TESTJNSABC IS

  -- FUNCTION IMPLEMENTATIONS
  FUNCTION get_num(num IN NUMBER) 
    RETURN SYS_REFCURSOR AS
    my_cursor SYS_REFCURSOR;
  BEGIN
    --
    OPEN my_cursor FOR 
    WITH ntable AS (
         SELECT 1 ID, 111 AGT, 'ABC' DESCRIP FROM DUAL
         UNION ALL
         SELECT 2 ID, 222 AGT, 'ABC' DESCRIP FROM DUAL
         UNION ALL
         SELECT 1 ID, 333 AGT, 'ABC' DESCRIP FROM DUAL
    )
    SELECT AGT FROM ntable WHERE ID = num;
    RETURN my_cursor;

  END;

  -- PROCEDURE IMPLEMENTATIONS 
  PROCEDURE testingabc AS
    --Creating a collection to hold return of the function
    type y is table of varchar2(1000) index by pls_integer; 
    var_z  y; 
    var_1 varchar2(100);

    BEGIN

     Select get_num(1)
     bulk collect into  var_z
     from dual;

    For i in 1..var_z.count
    loop

     WITH xtable AS (
         SELECT 111 AGT, 'A' DESCRIP FROM DUAL
         UNION ALL
         SELECT 222 AGT, 'B' DESCRIP FROM DUAL
         UNION ALL
         SELECT 333 AGT, 'C' DESCRIP FROM DUAL
     )
      SELECT DESCRIP
      into var_1 
      FROM xtable 
      WHERE AGT = var_z(i) ; ---Check each record

      dbms_output.put_line(var_1);

     end loop;

    END testingabc;

END TESTJNSABC;

答案 1 :(得分:0)

in ()需要子查询或以逗号分隔的值列表,所以不能,您不能替换返回集合的函数。

假设函数在SQL查询的范围内(它是独立函数或在包规范中声明),您可以在table()构造中使用它(这需要一个表函数,即它需要返回一个集合,而不是一个游标):

where somecol in (select column_value from table(get_num(1)) )

(或等效的内连接等)

livesql.oracle.com/apex/livesql/file/content_EF2M0F1LV9LTP6PEII3BDFKAI.html

演示

编辑:我刚刚注意到问题中的示例试图使用引用游标。请注意,table()运算符适用于集合,而不是ref游标。因此,该函数必须返回一个集合类型(嵌套表或varray)。

答案 2 :(得分:0)

根据@William Robertson的回答,我尝试实施解决方案,但遇到问题:

  

[错误] ORA-22905(18:26):PL / SQL:ORA-22905:无法访问来自的行   非嵌套表项

 -- FUNCTION IMPLEMENTATIONS
 create or replace  FUNCTION get_num(num IN NUMBER) 
    RETURN SYS_REFCURSOR AS
    my_cursor SYS_REFCURSOR;
  BEGIN
    --
    OPEN my_cursor FOR 
    SELECT AGT 
    FROM ntable 
    WHERE ID = num;

    RETURN my_cursor;

  END;

- 程序实施

CREATE OR REPLACE PROCEDURE testingabc
AS
type var is table of xtable.DESCRIP%type;    
v_var var;    
BEGIN
    SELECT DESCRIP
    bulk collect into var
     FROM xtable
    WHERE AGT IN (SELECT COLUMN_VALUE
                    FROM TABLE (get_num (1)));
END testingabc;