2017-01-16 6 views
0

Я получаю Ошибка:Oracle PL/SQL: Функция Cursor

PLS-00231: function 'GET_NUM' may not be used in 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).

+1

У вас есть некоторые вопросы здесь. Было бы проще помочь вам, если бы вы могли объяснить, что вы хотите, чтобы эти процедуры выполнялись. – Aleksej

+3

Ошибка кажется довольно ясной? Вы не можете использовать свою функцию в инструкции SQL, ее можно вызывать только из других контекстов PL/SQL (по крайней мере до 12c). –

+1

Вы не можете использовать функцию, возвращающую курсор ref таким образом. Он обычно используется в контексте передачи указателя набора результатов в PL/SQL. Вы можете приблизиться, но вам нужно будет использовать конвейерную функцию и не зная точно, что вы хотите, включая ответ, в том числе и бессмысленно. – BriteSponge

ответ

0

in() требует либо подзапрос или разделенный запятыми список значений, так что нет, вы не можете заменить функцию, которая возвращает коллекцию.

Предполагая, что функция доступна для SQL-запросов (она является автономной функцией или объявлена ​​в спецификации пакета), вы можете использовать ее в конструкции table() (для этого требуется функция таблицы, то есть она должна вернуть коллекцию, не курсор):

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

(или эквивалент внутреннего соединения и т.д.)

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

Edit: Я только что заметил пример в вопросе пытался использовать реф Curso р. Обратите внимание, что оператор table() работает с коллекциями, а не с рекурсивными курсорами. Поэтому функция должна возвращать тип коллекции (вложенная таблица или varray).

+0

Это не работает. Я точно сделал то же, что вы упомянули. Можете ли вы показать демонстрацию после того, как – XING

+0

Добавлена ​​ссылка на [LiveSQL demo] (https://livesql.oracle.com/apex/livesql/file/content_EF2M0F1LV9LTP6PEII3BDFKAI.html). –

+0

Не работает внутри блока plsql в приведенном выше примере, когда я заменяю 'SELECT DESCRIP FROM xtable WHERE COD_AGT IN get_num (1);' с 'SELECT DESCRIP FROM xtable WHERE AGT IN (выберите column_value из таблицы (get_num (1))) ' – XING

1

So is it possible then to create a variable on the Procedure and assign the Function values to the variable? Let's say

Не может быть вопроса, возможно ли это или нет, а не должно было быть, если это правильный путь. Конечно, вы можете сделать это так, как вы это делаете, но, как предложили эксперты, это неправильный и эффективный способ. Посмотрите, как вы можете это сделать. 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; 
+0

Спасибо @XING за вашу помощь. И какова наилучшая практика (более эффективный способ) выполнения этого? –

+0

Вы можете проверить, что предложил Boneist .. – XING

0

Согласно @William Robertson ответа, я попытался реализовать решение, но получая вопрос:

[Error] ORA-22905 (18: 26): PL/SQL: ORA-22905: cannot access rows from a non-nested table item

-- 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; 
+0

Оператор 'table()' работает с коллекциями, а не с курсорами. Я пропустил, что исходный вопрос попытался сделать это с помощью курсора ref. Добавлена ​​заметка к моему ответу. –

+0

Вот что я думал. Coz Я никогда не видел таких вещей и был более заинтересован узнать, может ли это случиться. – XING