несколько запросов в один ref-cursor

PooH_2
Дата: 21.11.2009 20:30:05
Господа, ткните ссылкой и подскажите как решить такую задачу: надо в процедуре/функции выполнить несколько динамических запросов и вернуть данные в одном ref-курсоре. Запросы похожи на такие:
v_sql:='select name, city from '||v_table_1|| 'where id = :id union all select name,city from '||v_table_2|| 'where id = :id';
в цикле меняются имена таблиц и в зависимости от параметров процедуры может быть разное количество проходов цикла. Ну и, соответственно, все эти данные надо получить в одном ref-курсоре. Собсnвенно, интересует в какую сторону лучше капать?
suPPLer
Дата: 21.11.2009 21:07:23
PooH_2,

копать лучше в сторону собирания строки запроса по параметрам. Большой строки с union all для запросов.
PooH_2
Дата: 21.11.2009 21:16:26
строку запроса собрать без проблем можно, но тогда возникает другой вопрос - как забиндить переменные? В USING насколько я понял не получится (так как кол-во зависит от параметров процедуры). Использовать DBMS_SQL - как из него потом ref-курсор получить (у меня 10.2)?
Залить данные в "TABLE OF ..." потом из них сделать каким-то боком Ref-курсор у меня в данный момент как-то не очень получается, да и способ не особо нравится...
Ну вот и решил спросить - может кто сталкивался с таким и подскажет направление для мыслИ?
PooH_2
Дата: 21.11.2009 21:18:05
... переименные хочется именно биндить, а не подставлять их значения в запрос
andreymx
Дата: 21.11.2009 21:55:06
для запроса из каждой таблицы разные переменные или один и тот же :id?
suPPLer
Дата: 21.11.2009 21:57:28
PooH_2,

есть вот такой вот вариант:
with binds as (select /*+ CARDINALITY(1) */ :p1 p1, :p2 p2 from dual)
select * 
  from (select x.object_id
          from all_objects x, binds
         where binds.p1 = binds.p2
         union all
        select 10
          from dual x) x, binds
 where binds.p1 = 1

Минусы: чтобы использовать переменные в (под)запросе, нужно добавлять binds в его кляузу FROM. И не поручусь, что не отразится на плане...
andreymx
Дата: 21.11.2009 22:08:49
create  or replace procedure t(abs out sys_refcursor)
is
v_sql_text varchar2(2000);
begin
v_sql_text := 'declare v_dummy varchar2(1) := :p_dummy;
begin
open :p_rec for ';

v_sql_text := v_sql_text || 'select * from dual where dummy = :p_dummy union all ';
v_sql_text := v_sql_text || 'select * from dual where dummy = :p_dummy union all ';
v_sql_text := v_sql_text || 'select * from dual where dummy = :p_dummy;';
v_sql_text := v_sql_text || 'end;';

--raise_application_error(-20101, v_sql_text);
execute immediate v_sql_text using in 'X', in abs;
end;


begin
t(:p_cur);
end;
PooH_2
Дата: 21.11.2009 22:12:11
andreymx,
один и тот же, то есть bind by name тут очень даже бы и подошел, но насколько я знаю если использовать "open v_cursor for v_sql using id,id" то id надо указывать столько раз сколько он встречается в v_sql (т.е. только bing by position возможен)

suPPLer,
то есть, собираем все запросы в одну строку, добавляем к ним что-то вроде "with binds as (select /*+ CARDINALITY(1) */ :p1 p1, :p2 p2 from dual))", биндим только эти переменные, а в самих запросах используем не переменные, а данные из этой view? я правильно понял?
andreymx
Дата: 21.11.2009 22:13:27
ну ты хоть запусти мой-то пример
PooH_2
Дата: 21.11.2009 22:15:57
О! А вариант с блоком (declare begin end) интересен, спасибо!