Gordolio
Gordolio

Reputation: 1997

oracle results from tables using function

I'm doing some testing to see if I can speed up a particular result set, but can't seem to get this particular solution working. I have data coming a few different tables and want to combine the data. I want to try this without using a union select to see if I get a performance improvement.

When I have a custom table/object type in a function, it seems to delete the existing data from the table when doing the subsequent select. Is there a way to do subsequent selects into the table without having the previous data deleted?

SQL Fiddle

Upvotes: 0

Views: 78

Answers (3)

Gordolio
Gordolio

Reputation: 1997

Thanks a_horse_with_no_name for pointing out that doing the multiple selects one at a time will probably be slower. I was able to reduce the execution time by filtering each select by student_id and then union-ing (rather than union-ing everything then filtering). On the data set I'm working with this solution was the fastest taking less than 1/10 of a second...

create or replace function
  academic_history(p_student_id number)
  return ah_tab_type
  is
  T ah_tab_type;
begin

  select ah_obj_type(student_id,course_code,grade)
  bulk collect
  into T
  from (
    select student_id,course_code,grade
    from completed_courses
    where student_id = p_student_id
    union
    select student_id,course_code,'P'
    from trans_courses
    where student_id = p_student_id);

  return T;
end;
/
select *
from table(academic_history(1));

and this took 2-3 seconds to execute...

create view vw_academic_history
select student_id,course_code,grade
from completed_courses
union
select student_id,course_code,'P'
from trans_courses;

select *
from vw_academic_history
where student_id = 1;

SQLFiddle.

Upvotes: 0

Alex Poole
Alex Poole

Reputation: 191570

As well as the multiset approach, if you really wanted to do this you could also make it a pipelined function:

create or replace function
academic_history(p_student_id number)
return ah_tab_type pipelined
is
    T ah_tab_type;
begin
    select ah_obj_type(student_id,course_code,grade)
    bulk collect
    into T
    from completed_courses
    where student_id = p_student_id;

    for i in 1..T.count loop
        pipe row (T(i));
    end loop;

    select ah_obj_type(student_id,course_code,'P')
    bulk collect
    into T
    from trans_courses
    where student_id = p_student_id;

    for i in 1..T.count loop
        pipe row (T(i));
    end loop;

    return;
end;

SQL Fiddle.

Upvotes: 0

user330315
user330315

Reputation:

I don't think that approach will be faster, in fact I expect it to be much slower.

But if you do want to do it, you need to put the rows from the second select into an intermediate collection and then join both using multiset union.

Something like this:

create or replace function
  academic_history(p_student_id number)
  return ah_tab_type
  is
  result ah_tab_type;
  t ah_tab_type;
begin

  select ah_obj_type(student_id,course_code,grade)
     bulk collect into result
  from completed_courses
  where student_id = p_student_id;

  select ah_obj_type(student_id,course_code,'P')
    bulk collect into T
  from trans_courses
  where student_id = p_student_id;

  result := result multiset union t;

  return result;
end;
/

Upvotes: 2

Related Questions