pl / sql - использование динамического запроса внутри хранимой процедуры - PullRequest
3 голосов
/ 15 февраля 2011

Я использую хранимую процедуру для вставки данных во временную таблицу с помощью курсора.Эта процедура сохраняет динамический запрос внутри переменной для монтирования команды вставки / обновления.

Вот код (не полный запрос, я вырезал некоторые части, чтобы его было легче читать):

 FOR VC2 IN (SELECT C.OBJETIVO,
                C.AUDITORIA ,
                C.NOME, 
                C.PRODUTO
           FROM CALCULO C)
  LOOP

  SELECT  ' V_UPD NUMBER := 0;

              SELECT (SELECT ID_TIPO_TERR  
              FROM ZREPORTYTD_TMP 
             WHERE AUDITORIA = ''' || VC2.AUDITORIA || '''
                AND TERRITORIO = ''' || VC2.NOME  || '''
                AND PRODUTO = ''' || VC2.PRODUTO || ''') 
               INTO V_UPD FROM DUAL;

                  UPDATE ZReportYTD_TMP
                     SET  TARGET = ' || VC2.OBJETIVO  || '
                   WHERE AUDITORIA = ''' || VC2.AUDITORIA || '''
                     AND TERRITORIO = ''' || VC2.NOME  || '''
                     AND PRODUTO = ''' || VC2.PRODUTO || ''';'

               INTO V_SQL  FROM DUAL;

               EXECUTE IMMEDIATE (V_SQL);

  END LOOP

Внутри динамического запроса, в этой части "SET TARGET = ' || VC2.OBJETIVO || '" значение VC2.OBJETIVO имеет тип Number и заменяется на "62481,76".Другими словами, эта запятая делает команду неправильной и не работает.

Существует ли простой способ заменить "," на "."?

Большое спасибо!(

Ответы [ 3 ]

15 голосов
/ 15 февраля 2011

Не создавайте запрос, добавляя строки.Вы оставляете себя открытым для множества ошибок и уязвимостей, прежде всего SQL-инъекций.Необходимость использования динамических запросов не оправдывает отказ от использования переменных связывания.Если вам действительно нужно использовать динамические запросы (из вашего примера непонятно, почему статическое обновление не работает ?!), сделайте это вместо этого:

FOR vc2 IN (...) LOOP
   v_sql := 
       'BEGIN
            V_UPD NUMBER := 0;

            SELECT (SELECT ID_TIPO_TERR  
              FROM ZREPORTYTD_TMP 
             WHERE AUDITORIA = :p1
               AND TERRITORIO = :p2
               AND PRODUTO = :p3) 
              INTO V_UPD FROM DUAL;

            UPDATE ZReportYTD_TMP
               SET TARGET = :p4
             WHERE AUDITORIA = :p5
               AND TERRITORIO = :p6
               AND PRODUTO = :p7;
        END';
   EXECUTE IMMEDIATE v_sql USING VC2.AUDITORIA, VC2.NOME, VC2.PRODUTO, 
                                 VC2.OBJETIVO, VC2.AUDITORIA, VC2.NOME, 
                                 VC2.PRODUTO;
END LOOP;

Oracle будет правильно связываться с соответствующим типом.1004 *

1 голос
/ 16 февраля 2011

Я вообще не вижу необходимости использовать динамический SQL.

Почему бы не что-то вроде:

FOR VC2 IN (SELECT C.OBJETIVO,
                C.AUDITORIA ,
                C.NOME, 
                C.PRODUTO
           FROM CALCULO C) LOOP

    v_upd := 0;

    SELECT
        ID_TIPO_TERR
    into
        v_UPD
    FROM
        ZREPORTYTD_TMP 
    WHERE
        AUDITORIA = VC2.AUDITORIA
    AND TERRITORIO = VC2.NOME
    AND PRODUTO = VC2.PRODUTO;

    -- is v_upd used anywhere?

    UPDATE
        ZReportYTD_TMP
    SET
        TARGET = VC2.OBJETIVO
    WHERE
        AUDITORIA = VC2.AUDITORIA
    AND TERRITORIO = VC2.NOME
    AND PRODUTO = VC2.PRODUTO;

END LOOP;
0 голосов
/ 11 марта 2013

Я использую Oracle 11g, последние пару дней я сталкивался с проблемой выполнить динамический запрос в оракуле. Я действительно много искал. наконец-то у меня есть решение.

-- In blow procedure we pass multiple argument at run time 
-- We need reference cursor for dynamic query execution
create or replace  PROCEDURE FETCH_REPORT1_NEW(IPID IN number ,CAID IN number,
ZOID IN  number,CLID IN number,SDATE VARCHAR2 , EDATE
VARCHAR2,OUT_VALUE OUT VARCHAR2)

IS

  l_sql varchar(200);   TYPE cursor_ref IS REF CURSOR;   c1
cursor_ref;

  UZID transaction_data.zone_id%TYPE;   OUTAGE_MINS
transaction_data.durationmin%TYPE;

BEGIN

    l_sql := 'select  Avg (durationmin) , zone_id ,
     from transaction_data where  alarm_id in (1,21,26,20) and  zone_id not in(5)';

      IF IPID>0 THEN  

       l_sql := l_sql||' and  IP_ID = '||IPID;

      END IF;         


        l_sql := l_sql||' group by (zone_id)';
       open c1 for l_sql;

          loop
              fetch c1 into OUTAGE_MINS,UZID;

                       dbms_output.put_line(OUTAGE_MINS||UZID);

              exit when c1%notfound;

          end loop;
     close c1; 
    END;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...