it is possible to use the with structure with a function inside a cursor, I don't know if I am declaring it inappropriately, I am getting the following error using with function inside procedure pl sql statement is not supported
CURSOR c_detail IS
WITH
FUNCTION CALC_NUMBER(FOB_ITEM NUMBER DEFAULT 0,
FOB_TOTAL NUMBER DEFAULT 0,
WEIGHT NUMBER DEFAULT 0) RETURN NUMBER
IS
PESO_BRUTO_ITEM NUMBER :=0;
BEGIN
IF( (FOB_ITEM > 0) AND (FOB_TOTAL > 0 AND WEIGHT> 0 )) THEN
PESO_BRUTO_ITEM := (FOB_ITEM * WEIGHT) / FOB_TOTAL;
END IF;
RETURN PESO_BRUTO_ITEM;
END CALC_NUMBER;
test_data AS
(
SELECT 36.25 AS FOB_I, 12536.36 AS FOB_TOTAL, 362 AS W FROM dual UNION ALL
SELECT 15.36 AS FOB_I, 3678.65 AS FOB_TOTAL, 362 AS W FROM dual UNION ALL
SELECT 878.77 AS FOB_I, 89653.13 AS FOB_TOTAL, 362 AS W FROM dual
)
SELECT TD.FOB_I,
TD.FOB_TOTAL,
CALC_NUMBER(TD.FOB_I, TD.FOB_TOTAL, TD.W) WEIGHT
FROM test_data TD
[TL;DR] You can declare a function in a sub-query factoring clause but (as Justin Cave points out ) it only works when you are executing the query as dynamic SQL and support for using functions in static SQL within a cursor may be available in future database versions.
This sub-query factoring clause with a function works outside of a cursor:
WITH
FUNCTION with_function(
p_id IN NUMBER
) RETURN NUMBER
IS
BEGIN
RETURN 42 + p_id;
END;
test_data ( id ) AS (
SELECT LEVEL FROM DUAL CONNECT BY LEVEL <= 3
)
SELECT id,
with_function( id )
FROM test_data;
Trying to put it into a cursor (in Oracle 18c):
DECLARE
p_id NUMBER;
p_fn NUMBER;
CURSOR c_detail IS
WITH
FUNCTION with_function(
p_id IN NUMBER
) RETURN NUMBER
IS
BEGIN
RETURN 42 + p_id;
END;
test_data ( id ) AS (
SELECT LEVEL FROM DUAL CONNECT BY LEVEL <= 3
)
SELECT id,
with_function( id )
FROM test_data;
BEGIN
OPEN c_detail;
LOOP
FETCH c_detail INTO p_id, p_fn;
EXIT WHEN c_detail%NOTFOUND;
DBMS_OUTPUT.PUT_LINE( p_id || ', ' || p_fn );
END LOOP;
CLOSE c_detail;
END;
/
Outputs the error:
\nORA-06550: line 7, column 14: \nPL/SQL: ORA-00905: missing keyword \nORA-06550: line 6, column 3: \nPL/SQL: SQL Statement ignored \nORA-06550: line 13, column 5: \nPLS-00103: Encountered the symbol "END" when expecting one of the following: \n\n begin function pragma procedure subtype type <an identifier> \n <a double-quoted delimited-identifier> current cursor delete \n exists prior\n
Removing the function then the cursor works:
DECLARE
p_id NUMBER;
CURSOR c_detail IS
WITH
test_data ( id ) AS (
SELECT LEVEL FROM DUAL CONNECT BY LEVEL <= 3
)
SELECT id
FROM test_data;
BEGIN
OPEN c_detail;
LOOP
FETCH c_detail INTO p_id;
EXIT WHEN c_detail%NOTFOUND;
DBMS_OUTPUT.PUT_LINE( p_id );
END LOOP;
CLOSE c_detail;
END;
/
So it is not an issue with using a sub-query factoring clause in a cursor.
Executing the cursor as dynamic SQL query:
DECLARE
p_id NUMBER;
p_fn NUMBER;
c_detail SYS_REFCURSOR;
p_sql VARCHAR2(4000) := 'WITH
FUNCTION with_function(
p_id IN NUMBER
) RETURN NUMBER
IS
BEGIN
RETURN 42 + p_id;
END;
test_data ( id ) AS (
SELECT LEVEL FROM DUAL CONNECT BY LEVEL <= 3
)
SELECT id,
with_function( id )
FROM test_data';
BEGIN
OPEN c_detail FOR p_sql;
LOOP
FETCH c_detail INTO p_id, p_fn;
EXIT WHEN c_detail%NOTFOUND;
DBMS_OUTPUT.PUT_LINE( p_id || ', ' || p_fn );
END LOOP;
CLOSE c_detail;
END;
/
Works and outputs:
\n1, 43 \n2, 44 \n3, 45 \n
So it appears that, yes, you can declare a function in a sub-query factoring clause but it only works when you are executing the query as dynamic SQL.
db<>fiddle here
The error message clearly says you can't do what you are after, but then you will not have to if your cursor looks like following
CURSOR c_detail IS
WITH test_data AS(
SELECT 36.25 AS FOB_I, 12536.36 AS FOB_TOTAL, 362 AS W FROM dual UNION ALL
SELECT 15.36 AS FOB_I, 3678.65 AS FOB_TOTAL, 362 AS W FROM dual UNION ALL
SELECT 878.77 AS FOB_I, 89653.13 AS FOB_TOTAL, 362 AS W FROM dual
)
SELECT TD.FOB_I,
TD.FOB_TOTAL,
CASE WHEN TD.FOB_I > 0 AND TD.FOB_TOTAL > 0 AND TD.W > 0
THEN (TD.FOB_I * TD.W) / TD.FOB_TOTAL
ELSE 0
END WEIGHT
FROM test_data TD
;
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.