Reputation: 18433
Is is possible to join Oracle table valued function? i want query and inner join fuction. How to join?
Query Oracle
FUNCTION FNC_LST_OUR(p_code varchar2,
p_pm_from varchar2,
p_pm_to varchar2
) return VARCHAR2 is
v_sql2 VARCHAR2(30000) := '';
v_sql VARCHAR2(30000) := '';
number_out NUMBER := 0;
error_msg_tmp varchar2(255);
begin
v_sql := 'select s.com_code, s.pn_code, count(*) as our
from pmtest s
inner join PMOP_TEST l on s.com_code=l.com_code and s.pn_code=l.pn_code
where s.com_code = ''' || p_code ||
';
if p_pm_from is not null then
v_sql := v_sql || ' and s.pn_code between ''' || p_pm_from || ''' and ''' || p_pm_to || '''';
end if;
v_sql := v_sql || ' group by s.com_code,s.pn_code
having count(s.pn_code)> 0 ';
EXECUTE IMMEDIATE v_sql INTO v_sql2;
RETURN v_sql2;
exception
when OTHERS THEN
error_msg_tmp := substr(sqlcode || ' - ' || sqlerrm, 1, 200);
RETURN v_sql2;
end;
Statement Query
select a.*
from PMOP_TEST l
inner join table(packages.FNC_LST_OUR('test','test','test')) a on l.com_code=a.com_code and a.pn_code=l.pn_code
Error Query on statement : ORA-22905
Sample Data Function
com_code | pn_code | OUR
AAA | AW |0
AAA | AQ |5
AAB | AQ |10
AAA | CV |2
Sampla Data Statement Table PMOP_TEST
com_code | pn_code | DESCRIPT
AAA | AW | test1
AAA | AQ | test2
AAB | AQ | test2
AAA | CV | test3
AAB | FG | test1
i want join function value result:
com_code | pn_code | DESCRIPT | OUR
AAA | AW | test1 | 0
AAA | AQ | test2 | 5
AAA | CV | test3 | 2
Help me please. thanks advance ;)
Upvotes: 1
Views: 2119
Reputation: 167922
Your dynamic query can be represented in SQL like this (specifying the inputs as bind variables):
select s.com_code, s.pn_code, count(*) as our
from pmtest s
inner join PMOP_TEST l
on (s.com_code=l.com_code and s.pn_code=l.pn_code)
where s.com_code = :p_code
and ( :p_pm_from IS NULL OR s.pn_code between :p_pm_from and :p_pm_to )
group by s.com_code,s.pn_code
Then you can join it to your other query like this:
select a.*
from PMOP_TEST l
inner join (
select s.com_code,
s.pn_code,
count(*) as our
from pmtest s
inner join PMOP_TEST l
on (s.com_code=l.com_code and s.pn_code=l.pn_code)
where s.com_code = :p_code
and ( :p_pm_from IS NULL OR s.pn_code between :p_pm_from and :p_pm_to )
group by s.com_code,s.pn_code
) a
on l.com_code=a.com_code and a.pn_code=l.pn_code
And you have done it all with SQL and don't need to use collections or pipelined queries.
Upvotes: 1
Reputation: 94884
You are probably looking for a pipelined function that returns a table of records. In order to write it you need a record type for the columns the function is to return and a table type for the rows:
create or replace type fnc_lst_our_record is record(com_code number, pn_code number, our number);
create or replace type fnc_lst_our_table is table of fnc_lst_our_record;
Then write the function using the types. You don't need any dynamic SQL for this by the way.
create or replace function fnc_lst_our
(
p_code varchar2,
p_pm_from varchar2,
p_pm_to varchar2
) return fnc_lst_our_table pipelined is
begin
for rec in
(
select s.com_code, s.pn_code, count(*) as our
from pmtest s
inner join pmop_test l on s.com_code = l.com_code and s.pn_code = l.pn_code
where s.com_code = p_code
and (p_pm_from is null or p_pm_from s.pn_code between p_pm_from and p_pm_to)
group by s.com_code,s.pn_code
having count(s.pn_code) > 0 -- this clause is superfluous
) loop
pipe fnc_lst_our_record(rec.com_code, rec.pn_code, rec.our);
end loop;
end;
You call this function exactly as you tried.
Upvotes: 0
Reputation: 1948
Sample:
CREATE TYPE FNC_LST_OUR_TYPE AS OBJECT
(
com_code VARCHAR2 (20),
pn_code VARCHAR2 (20),
our NUMBER
);
/
CREATE TYPE FNC_LST_OUR_TYPE_T AS TABLE OF FNC_LST_OUR_TYPE;
/
CREATE OR REPLACE PACKAGE pkg
AS
FUNCTION FNC_LST_OUR (p_code VARCHAR2, p_pm_from VARCHAR2, p_pm_to VARCHAR2)
RETURN FNC_LST_OUR_TYPE_T
PIPELINED;
END;
/
CREATE OR REPLACE PACKAGE BODY pkg
AS
FUNCTION FNC_LST_OUR (p_code VARCHAR2, p_pm_from VARCHAR2, p_pm_to VARCHAR2)
RETURN FNC_LST_OUR_TYPE_T
PIPELINED
IS
c SYS_REFCURSOR;
v_result FNC_LST_OUR_TYPE;
BEGIN
OPEN c FOR 'select FNC_LST_OUR_TYPE(''AAA'' , ''AW'' , 0 ) from dual
union all
select FNC_LST_OUR_TYPE(''AAA'' , ''AQ'' , 5) from dual
union all
select FNC_LST_OUR_TYPE(''AAB'' , ''AQ'' , 10) from dual
union all
select FNC_LST_OUR_TYPE(''AAA'' , ''CV'', 2) from dual';
LOOP
FETCH c INTO v_result;
EXIT WHEN c%NOTFOUND;
PIPE ROW (v_result);
END LOOP;
END;
END;
/
And use it:
SELECT * FROM TABLE ( PKG.FNC_LST_OUR ('A', 'B', 'C') )
Look at Table Functions
Upvotes: 0