oracle-databasefunctionfor-loopexecutequery

Run a query script inside a for in loop (Oracle)


I have a function as you can see below. I have a query string because i need to execute it with a parameter. My problem is: how can i put the query inside the "for"? I've tried with

EXECUTE IMMEDIATE query_string 

in my for loop but it doesn't work.

Anyone?

Regards!

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;

Solution

  • You shouldn't concatenate data into your query. Use bind variables. Read up on SQL Injection, and hard parsing to see two reasons why you should use bind variables.

    You might try something like the following (no need for loops at all):

      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;