2015-07-06 2 views
0

У меня есть функция, как вы можете видеть ниже. У меня есть строка запроса, потому что мне нужно выполнить ее с параметром. Моя проблема: как я могу поставить запрос внутри «for»? Я пробовал сЗапуск сценария запроса внутри цикла for for (Oracle)

EXECUTE IMMEDIATE query_string 

в мой цикл, но он не работает.

Кто-нибудь?

С уважением!

create or replace FUNCTION RO_FUN_TOTAL_SCORE_DATE_PORTAL 
(
    v_DATE_FIELD IN VARCHAR2 
) RETURN RO_OBJ_NESTED_TOTAL_SCORE IS 
    v_ret    RO_OBJ_NESTED_TOTAL_SCORE; 
    query_string  VARCHAR2(1000); 
BEGIN 
    /*Initialize object type to save data*/ 
    v_ret := RO_OBJ_NESTED_TOTAL_SCORE(); 

    query_string := 'SELECT ROUND(AVG(generic_score),2) AS score, 
    yrp.comment_date_pk AS comment_date, 
    yrp.hot_id_pk AS hot_id, 
    yp.portal_id_pk AS portal_id, 
    AVG(total_opinions) AS total_opinions 
    FROM yrportalreview yrp JOIN yrhotellinks yrh ON yrp.hot_id_pk = 
    yrh.hot_id 
    AND yrp.portal_id_pk = yrh.portal_id AND yrp.comment_date.pk = ' ||  
    v_DATE_FIELD || 
    ' WHERE yrp.hot_id_pk IN (92, 27) 
    AND concept_id_pk = 1 
    AND yp.active = 1 
    GROUP BY hot_id_pk, 
    yp.portal_id_pk, 
    yrp.comment_date_pk'; 

FOR I IN (EXECUTE IMMEDIATE query_string) 
    LOOP 
    /*insert in table type rows with data*/ 
    v_ret.extend; 
    v_ret(v_ret.count) := RO_OBJ_TOTAL_SCORE_DATE_PORTAL(i.score, 
     i.comment_date, i.hot_id, i.portal_id, i.total_opinions); 
    END LOOP; 
    RETURN v_ret; 
END RO_FUN_TOTAL_SCORE_DATE_PORTAL; 
+0

Зачем вам использовать динамический SQL здесь? Почему бы вам не использовать статический SQL? Почему вы хотите использовать цикл, а не делать 'bulk collect' в свою коллекцию? Если вы хотите использовать цикл, уверены ли вы, что не хотите использовать функцию конвейерной таблицы? –

+0

Я согласен, ничего не может быть сделано с помощью курсора, нет необходимости использовать execute немедленно – kevinsky

ответ

0

Вы не должны конкатенации данных в запрос. Используйте переменные bind. Прочитайте SQL Injection и жесткий синтаксический анализ, чтобы увидеть две причины, по которым вы должны использовать переменные связывания.

Вы можете попробовать что-то вроде следующего (нет необходимости петель на всех):

create or replace FUNCTION RO_FUN_TOTAL_SCORE_DATE_PORTAL 
    (
    v_DATE_FIELD IN VARCHAR2 
) RETURN RO_OBJ_NESTED_TOTAL_SCORE IS 
    v_ret    RO_OBJ_NESTED_TOTAL_SCORE; 

    BEGIN 

    SELECT RO_OBJ_TOTAL_SCORE_DATE_PORTAL 
       (ROUND(AVG(generic_score),2) -- score, 
       ,yrp.comment_date_pk   -- comment_date 
       ,yrp.hot_id_pk    -- hot_id 
       ,yp.portal_id_pk    -- portal_id 
       ,AVG(total_opinions))   -- total_opinions 
    BULK COLLECT INTO v_ret 
    FROM yrportalreview yrp 
    JOIN yrhotellinks yrh 
      ON yrp.hot_id_pk = yrh.hot_id 
      AND yrp.portal_id_pk = yrh.portal_id 
      AND yrp.comment_date.pk = v_DATE_FIELD 
    WHERE yrp.hot_id_pk IN (92, 27) 
     AND concept_id_pk = 1 
     AND yp.active = 1 
    GROUP BY hot_id_pk, 
     yp.portal_id_pk, 
     yrp.comment_date_pk'; 

    RETURN v_ret; 
    END RO_FUN_TOTAL_SCORE_DATE_PORTAL; 
+0

Я понимаю, но моя проблема: поле yrp.comment_date_pk - это дата, а содержимое v_DATE_FIELD - это строка с именем поле для сравнения, а не с самой датой. – Light1988

+0

Сколько различных возможных значений может иметь значение v_DATE_FIELD? Вы можете использовать DECODE или CASE для сопоставления v_DATE_FIELD с столбцом: 'DECODE (v_DATE_FIELD, 'C1', yrh.c1, 'C2', yrh.c2)' – daivrz

+0

Да DECODE !! Это то что мне нужно. Спасибо!! – Light1988

0

Нечто подобное, которые работали для типов испытаний и данных:

create or replace function f_test(v_date_field in varchar2) return t_test_tab is 

    v_ret t_test_tab; 
    v_sql varchar2(4000); 
begin 
    v_sql := 'select t_test_row(id, date1) from test where date1 = '||v_date_field; 
    execute immediate v_sql bulk collect into v_ret; 
    return v_ret; 
end f_test; 

определений данных и испытания:

create table test (id number, date1 date, date2 date, date3 date); 
insert into test values (1, date '2015-01-01', date '2015-01-01', date '2015-01-02'); 
insert into test values (2, date '2015-01-02', date '2015-01-01', date '2015-01-02'); 

create type t_test_row is object (id number, date1 date); 
create type t_test_tab is table of t_test_row; 

select * from table(f_test('DATE2')); 

ID DATE1 
-- ---------- 
1 2015-01-01