I want to write two pipelined functions, standalone, meaning outside of PL/SQL package:
create or replace function fn_test_1
return sys.DBMS_DEBUG_VC2COLL pipelined -- ODCIVARCHAR2LIST
AS
BEGIN
FOR l_row in ( ... )
LOOP
PIPE ROW('text');
PIPE ROW('other text');
PIPE ROW(strings_concatenated);
END LOOP;
END;
/
create or replace function fn_test_2
return sys.DBMS_DEBUG_VC2COLL pipelined -- ODCIVARCHAR2LIST
AS
BEGIN
FOR l_row in ( select column_value as line from TABLE( fn_test_1 ) )
LOOP
PIPE ROW(l_row);
END LOOP;
END;
/
fn_test_1 compiles successfully and works fine. However I cannot compile fn_test_2 becuase of:
PLS-00382: expression is of wrong type
Can I even write standalone pipelined functions one calling the other?
You're return a cursor and not the value it has, use this:
create or replace function fn_test_2
return sys.DBMS_DEBUG_VC2COLL pipelined -- ODCIVARCHAR2LIST
AS
BEGIN
FOR l_row in ( select column_value as line from TABLE( fn_test_1 ) )
LOOP
PIPE ROW(l_row.line);
END LOOP;
END;
/
Related
This function is inside a package, but when I call the function the following error appears: PL/SQL "all_search" is not a procedure or is undefined. Someone can help me?
CREATE OR REPLACE PACKAGE employee_tab IS
FUNCTION all_search (ID_EMP in NUMBER) RETURN O_T_EMPL PIPELINED;
END employee_tab;
/
CREATE OR REPLACE TYPE O_T_EMPL AS TABLE OF O_EMPLOYEE;
/
CREATE OR REPLACE PACKAGE BODY employee_tab IS
FUNCTION all_search (ID_EMP in NUMBER) RETURN O_T_EMPL PIPELINED
IS
TAB_OBJC_EMP O_T_EMPL;
MY_QUERY_SEARCH VARCHAR2(400);
REF_C SYS_REFCURSOR;
MAX_ROW NUMBER := 25;
BEGIN
MY_QUERY_SEARCH := 'SELECT *
FROM EMPLOYEES
WHERE EMPLOYEE_ID = ID_EMP';
open REF_C for MY_QUERY_SEARCH using ID_EMP;
loop
--
fetch REF_C bulk collect into TAB_OBJC_EMP limit MAX_ROW;
exit when TAB_OBJC_EMP.count = 0;
for i in 1..TAB_OBJC_SEE.count
--
loop
pipe row(O_EMPLOYEE(TAB_OBJC_EMP(i).V_O_EMP_ID,
TAB_OBJC_EMP(i).V_O_HIRE_ID,
TAB_OBJC_EMP(i).V_O_DEP_ID)
);
end loop;
--
END loop;
--
CLOSE REF_C;
RETURN;
--
END all_search;
END employee_tab;
/
call function: employee_tab.all_search(1);
You need to assign the result of the function to something, try something like:
DECLARE
l_emp_id NUMBER;
BEGIN
SELECT EMP_ID
INTO l_emp_id
FROM TABLE(employee_tab.all_search(1))
WHERE rownum = 1;
DBMS_OUTPUT.put_line(TO_CHAR(EMP_ID));
END;
/
I'm trying to write a pipelined function which uses another pipelined function several times.
So, function context_Set receives a cursor and returns results that should be used several times in pipelined funcion m0 which also receives a cursor as an argument (the sql logic is simplified to UNION):
create or replace PACKAGE BODY PKG_PIPE AS
FUNCTION context_Set(l_res sys_refcursor)
RETURN resulting_cols_rt PIPELINED
IS
recs resulting_record_rt;
BEGIN
loop
fetch l_res into recs;
exit when l_res%notfound;
PIPE ROW(recs);
end loop;
close l_res;
return;
END context_Set;
-------------------- BEGIN: 01.TEST ---------------------
FUNCTION m0(l_res sys_refcursor)
RETURN resulting_cols_rt PIPELINED
IS
recs resulting_record_rt;
l_in_res SYS_REFCURSOR;
BEGIN
open l_in_res for
select resulting_record_rt(c1,c2,c3,c4) FROM (
SELECT * FROM context_Set(l_res)
UNION ALL
SELECT * FROM context_Set(l_res));
loop
fetch l_in_res into recs;
exit when l_in_res%notfound;
PIPE ROW(recs);
end loop;
close l_in_res;
return;
END m0;
END PKG_PIPE;
and the function is called like the following:
open l_res for 'select resulting_record_rt(c1,c2,c3,c4) from (select ... )';
select *
FROM PKG_PIPE.m0(l_res);
close l_res;
The error I'm getting is:
ORA-01001: invalid cursor
When UNION and the second SELECT are removed the function works fine.
Is there some way to rewrite the same to make it work?
I have a package with 2 pipelined functions. When I'm trying to call one function with another function as it's argument I'm getting "ORA-06553: PLS-306: wrong number or types of arguments in call" error.
Here is the package:
create or replace NONEDITIONABLE TYPE RESULTING_RECORD_RT as object
(
CALENDAR NVARCHAR2(1024),
PRODUCT NVARCHAR2(1024),
MEASURE NVARCHAR2(1024),
VALUE NUMBER
);
/
create or replace NONEDITIONABLE TYPE RESULTING_COLS_RT IS TABLE OF RESULTING_RECORD_RT;
/
create or replace package pipe_pkg as
function pipe_func_emp return RESULTING_COLS_RT PIPELINED;
function pipe_func_emp2(input_Set IN resulting_cols_rt) return RESULTING_COLS_RT PIPELINED;
end;
/
create or replace package body pipe_pkg as
function pipe_func_emp return RESULTING_COLS_RT
PIPELINED
is
test_tbl resulting_cols_rt:= resulting_cols_rt();
begin
test_tbl.extend;
test_tbl(1):=resulting_record_rt('A','B','C',1);
test_tbl.extend;
test_tbl(2):=resulting_record_rt('A','B','D',2);
PIPE ROW(test_tbl(1));
PIPE ROW(test_tbl(2));
return;
end;
function pipe_func_emp2(input_Set IN resulting_cols_rt) return RESULTING_COLS_RT
PIPELINED
is
v_tmp NVARCHAR2(10240);
l_res SYS_REFCURSOR;
recs resulting_record_rt;
begin
open l_res for select * from table(input_Set);
loop
fetch l_res into recs;
PIPE ROW(recs);
exit when l_res%notfound;
end loop;
close l_res;
return;
end;
end;
/
I'm calling the functions as follows:
select * from TABLE(pipe_pkg.pipe_func_emp2(CURSOR(select * from TABLE(pipe_pkg.pipe_func_emp()))));
And the call throws error:
ORA-06553: PLS-306: wrong number or types of arguments in call to 'PIPE_FUNC_EMP2'
06553. 00000 - "PLS-%s: %s"
What am I doing wrong?
The function pipe_func_emp2 expected RESULTING_COLS_RT as it's argument, but got REF CURSOR. These are incompatible types.
Try following reproducible example of a chaining of the pipelined functions:
create or replace type somerow as object (id int, val varchar2 (8))
/
create or replace type sometab is table of somerow
/
create or replace package pack as
function func1 return sometab pipelined;
function func2 (cur sys_refcursor) return sometab pipelined;
end;
/
create or replace package body pack as
function func1 return sometab pipelined is
tab sometab := sometab (somerow (1,'AAA'), somerow (2,'BBB'));
begin
for i in 1..tab.count loop
pipe row (tab(i));
end loop;
return;
end;
function func2 (cur sys_refcursor) return sometab pipelined is
sr somerow;
begin
loop
fetch cur into sr;
exit when cur%notfound;
pipe row (sr);
end loop;
close cur;
return;
end;
end;
/
The query and it's outcome:
select *
from table (pack.func2 (
cursor (select value (p) from table (pack.func1()) p )))
/
ID VAL
---------- --------
1 AAA
2 BBB
I have to write a nested pipelined function in pl/sql which I tried implementing in the following manner.
create package body XYZ AS
function main_xyz return data_type_1 pipelined is
begin
--code
pipe row(sub_func);
end;
function sub_func return data_type_1 pipelined is
begin
--code
pipe row(sub_func_1);
end;
function sub_func_1 return data_type_1 pipelined is
begin
--code
pipe row(main_abc);
end;
end;
create package body abc AS
function main_abc return data_type_2 pipelined is
var data_type_2;
begin
--code
return var;
end;
end;
However, I get the following error
[Error] PLS-00653 : PLS-00653: aggregate/table functions are not
allowed in PL/SQL scope
Where am I going wrong? Is it syntax or logic?
Pipelined functions provide rows one by one (on demand), so you cannot put all the rows at one time from pipelined function.
Seems to me you need to change main_xyz this way:
function main_xyz return data_type_1 pipelined is
begin
--code
FOR rec IN (select * from table(XYZ.sub_func)) LOOP
pipe row(rec);
END LOOP;
end;
Consider that sub_func must be in specification of XYZ package since everything you use in SQL queries including PIPELINED functions are to be public (i.e. visible to a user who runs query).
UPDATE: I forget to alert: do not abuse pipelined functions (if you have another choice) - queries using them might have lame performance because DB engine cannot build a good execution plan for "unpredictable piped rows".
I wrote this code in pl/sql but I couldnt take answer.
create or replace function mostafa.sbs_Topic_LedgerBalance8Column
(BranchID number,DateFrom number,DateTo number)
RETURN SYS_REFCURSOR
IS O_RESULT SYS_REFCURSOR;
BEGIN
open O_RESULT for
Select s* From Mostafa.topic ;
RETURN O_RESULT;
end sbs_Topic_LedgerBalance8Column;
and I called it this way:
DECLARE v_refcursor SYS_REFCURSOR;
BEGIN
v_refcursor :=mostafa.sbs_topic_ledgerbalance8column(12,12,12);
FOR employee_rec IN v_refcursor
LOOP
DBMS_OUTPUT.put_line (
employee_rec.ID);
END LOOP;
end;
why did I get error when I retrieve result?
error is :v_refcursor is not a procedure or is undefined
When you are using a refcursor, you can't access it by using the cursor for loop. Use something like the following instead (Untested):
DECLARE
v_refcursor SYS_REFCURSOR;
v_emp_rec topic%ROWTYPE;
BEGIN
v_refcursor :=mostafa.sbs_topic_ledgerbalance8column(12,12,12);
LOOP
FETCH v_refcursor INTO v_emp_rec;
EXIT WHEN v_refcursor%NOTFOUND;
DBMS_OUTPUT.PUT_LINE(v_emp_rec.id);
END LOOP;
close v_refcursor;
END;