pl/sql - 在存储过程中使用动态查询

发布于 2024-10-17 16:08:07 字数 1205 浏览 2 评论 0原文

我正在使用存储过程使用游标将数据插入到临时表中。 此过程将动态查询存储在变量内以安装插入/更新命令。

这是代码(不是完整的查询,我删除了一些部分以使其更易于阅读):

 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 || '"< /code> 值 VC2.OBJETIVO 是一个 Number 类型,它被替换为“62481,76”。换句话说,这个逗号使命令错误并且不起作用。

有没有一种简单的方法可以将“,”替换为“.”?

非常感谢! (:

I am using a stored procedure to insert data into a temp table using a cursor.
This procedure stores a dynamic query inside a variable to mount the insert/update command.

Here is the code(not the full query, I've cut some parts to make it easier to read):

 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

Inside the dynamic query, in this part "SET TARGET = ' || VC2.OBJETIVO || '" the value VC2.OBJETIVO is a Number type, and it's replaced like "62481,76". In other words, this comma is making the command wrong and doesn't work.

Is there an easy way to replace the "," for "."?

Thank you very much! (:

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

黎夕旧梦 2024-10-24 16:08:07

不要通过附加字符串来构建查询。您会让自己面临许多错误和漏洞,首先是 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 将正确绑定适当的类型。

Don't build your query by appending strings. You leave yourself open to lots of bugs and vulnerabilities, first of all SQL injection. The need to use dynamic queries doesn't justify not using bind variables. If you really need to use dynamic queries (it is not clear from your example why static update wouldn't work?!), do this instead:

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 will correctly bind with the appropriate type.

单身狗的梦 2024-10-24 16:08:07

我认为根本没有必要使用动态 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;

I don't see any need to use dynamic SQL at all.

Why not something like:

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;
写给空气的情书 2024-10-24 16:08:07

我正在使用 Oracle 11g,最近几天我遇到了以下问题
在oracle过程中执行动态查询。我确实搜索了很多。
终于我找到了解决方案。

-- 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;

I am using Oracle 11g , last couple of day I was facing problem of
execute dynamic query in oracle procedure. I did search lots off.
finally i have got solution .

-- 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;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文