• 在Oracle中执行动态SQL的几种方法------转载


    在Oracle中执行动态SQL的几种方法

    在一般的sql操作中,sql语句基本上都是固定的,如:
    SELECT t.empno,t.ename  FROM scott.emp t WHERE t.deptno = 20;
    但有的时候,从应用的需要或程序的编写出发,都可能需要用到动态SQl,如:
    当 from 后的表 不确定时,或者where 后的条件不确定时,都需要用到动态SQL。

    一、使用动态游标实现
    1、声明动态游标
    TYPE i_cursor_type IS REF CURSOR;
    2、声明游标变量
    my_cursor i_cursor_type;
    3、使用游标
    n_deptno:=20;
    dyn_select := 'select empno,ename from emp where deptno='||n_deptno;
    OPEN my_cursor FOR dyn_select;
    LOOP 
      FETCH my_cursor INTO n_empno,v_ename;
      EXIT WHEN my_cursor%NOTFOUND;
      --用n_empno,v_ename做其它处理
      --....
    END LOOP;
    CLOSE dl_cursor;
    4、小结:动态游标可以胜任大多数动态SQL的需求了,使用简洁方便居家旅行之必备杀人放火之法宝。

    二、使用 EXECUTE IMMEDIATE
    最早大家都使用DBMS_SQL包,但是太太麻烦了,最终都放弃了。但是自从有了EXECUTE IMMEDIATE之后,但要注意以下几点:
    EXECUTE IMMEDIATE代替了以前Oracle8i中DBMS_SQL package包.它解析并马上执行动态的SQL语句或非运行时创建的PL/SQL块.动态创建和执行SQL语句性能超前,EXECUTE IMMEDIATE的目标在于减小企业费用并获得较高的性能,较之以前它相当容易编码.尽管DBMS_SQL仍然可用,但是推荐使用EXECUTE IMMEDIATE,因为它获的收益在包之上。 
     使用技巧

    1. EXECUTE IMMEDIATE将不会提交一个DML事务执行,应该显式提交
     如果通过EXECUTE IMMEDIATE处理DML命令,那么在完成以前需要显式提交或者作为EXECUTE IMMEDIATE自己的一部分. 如果通过EXECUTE IMMEDIATE处理DDL命令,它提交所有以前改变的数据

    2. 不支持返回多行的查询,这种交互将用临时表来存储记录(参照例子如下)或者用REF cursors.

    3. 当执行SQL语句时,不要用分号,当执行PL/SQL块时,在其尾部用分号.

    4. 在Oracle手册中,未详细覆盖这些功能。下面的例子展示了所有用到Execute immediate的可能方面.希望能给你带来方便.

    5. 对于Forms开发者,当在PL/SQL 8.0.6.3.版本中,Forms 6i不能使用此功能.

    EXECUTE IMMEDIATE用法例子

    1. 在PL/SQL运行DDL语句


     begin
      execute immediate 'set role all';
     end;

    2. 给动态语句传值(USING 子句)


     declare
      l_depnam varchar2(20) := 'testing';
      l_loc    varchar2(10) := 'Dubai';
      begin
      execute immediate 'insert into dept values  (:1, :2, :3)'
        using 50, l_depnam, l_loc;
      commit;
     end;

    3. 从动态语句检索值(INTO子句)


     declare
      l_cnt    varchar2(20);
     begin
      execute immediate 'select count(1) from emp'
        into l_cnt;
      dbms_output.put_line(l_cnt);
     end;

    4. 动态调用例程.例程中用到的绑定变量参数必须指定参数类型.黓认为IN类型,其它类型必须显式指定

     declare
      l_routin   varchar2(100) := 'gen2161.get_rowcnt';
      l_tblnam   varchar2(20) := 'emp';
      l_cnt      number;
      l_status   varchar2(200);
     begin
      execute immediate 'begin ' || l_routin || '(:2, :3, :4); end;'
        using in l_tblnam, out l_cnt, in out l_status;

      if l_status != 'OK' then
         dbms_output.put_line('error');
      end if;
     end;

    5. 将返回值传递到PL/SQL记录类型;同样也可用%rowtype变量


     declare
        type empdtlrec is record (empno  number(4),ename  varchar2(20),deptno  number(2));
        empdtl empdtlrec;
     begin
        execute immediate 'select empno, ename, deptno '||'from emp where empno = 7934'
        into empdtl;
     end;

    6. 传递并检索值.INTO子句用在USING子句前

     declare
       l_dept    pls_integer := 20;
       l_nam     varchar2(20);
       l_loc     varchar2(20);
     begin
        execute immediate 'select dname, loc from dept where deptno = :1'
           into l_nam, l_loc
           using l_dept ;
     end;

    7. 多行查询选项.对此选项用insert语句填充临时表,用临时表进行进一步的处理,也可以用REF cursors纠正此缺憾.
     
     declare
      l_sal   pls_integer := 2000;
     begin
      execute immediate 'insert into temp(empno, ename) ' ||
                       '          select empno, ename from emp ' ||
                       '          where  sal > :1'
        using l_sal;
      commit;
     end;

           对于处理动态语句,EXECUTE IMMEDIATE比以前可能用到的更容易并且更高效.当意图执行动态语句时,适当地处理异常更加重要.应该关注于捕获所有可能的异常.

     
     

    一。为什么要使用动态执行语句?

           由于在PL/SQL 块或者存储过程中只支持DML语句及控制流语句,并不支持DDL语句,所以Oracle动态执行语句便应允而生了。关于DDL与DML的区别,请参见:DDL语句与DML语句及DCL和TCL

    二。动态执行语句怎么用?     

         动态执行语句代替了Oracle 8i中的DBMS_SQL Package包。

         1)在PL/SQL中运行SQL语句,例如:

           示例一:

            BEGIN 
                  EXECUTE IMMEDIATE 'select count(username) from user_users';     --DML每条语句必须以分号结尾
           END;

           示例二:

           BEGIN 
                   EXECUTE IMMEDIATE  'ALTER TABLE a RENAME TO EXAMPLE';    --DDL
            END;

            你可能会问不是只DDL语句需要用动态语句执行吗?是的,你说的完全正确。但是DML语句用动态语句执行也可以。

            即:DDL语句只能用动态执行语句来执行,DML语句亦可用动态语句来执行。

        2)使用using给动态语句传值,例如:

             DECLARE
                    e_name VARCHAR2(10); --声明变量e_name
                    e_age INT;                        --声明变量e_age
             BEGIN
                    e_name :=  'sillylaura';      --给变量e_name赋值
                    e_age := 21;                     --给变量e_age 赋值
                    EXECUTE IMMEDIATE 'insert into Example values(seq_add_by_one.nextval,:2,:3)' using e_name,e_age;  --DML             END;

        3)使用动态语句赋值(select 列名 into 变量 from ……)

             DECLARE 
                            temp INT; 
             BEGIN
                            EXECUTE IMMEDIATE 'SELECT COUNT(*) FROM dual'  INTO temp; --DML

                            dbms_output.put_line(temp);
             END;

         4)传递并检索值:into用在using之前。

             DECLARE
                       temp INT;
                       test VARCHAR2(10);
             BEGIN
                     test := 'ok';
                     EXECUTE immediate 'SELECT COUNT(*) FROM dual where dummy = :1 GROUP BY dummy' INTO temp USING test;
                     dbms_output.put_line(temp ||'  '|| test); 
             EXCEPTION WHEN OTHERS  THEN 
                     dbms_output.put_line('It has no data!'); 
             END;

    三。动态语句小结

      1. DDL语句只能用动态执行语句来执行,DML语句亦可用动态语句来执行。
      2. 在使用select……into子句为变量赋值时,into字句必须写在单引号外面。
      3. 在同时使用select……into子句和using时,注意二者的顺序:into用在using之前,且都在单引号外面。
      4. 注意写上必要的异常错误处理。
  • 相关阅读:
    为什么页面设计宽度要控制在960px
    RRDtool运用
    cacti监控jvm
    cacti安装
    rConfig v3.9.2 授权认证与未授权RCE (CVE-2019-16663) 、(CVE-2019-16662)
    Linux安全学习
    Github-Dorks与辅助工具
    警方破获超大DDoS黑产案,20万个僵尸网络运营商被抓
    SRC漏洞挖掘
    威胁情报木马病毒样本搜集
  • 原文地址:https://www.cnblogs.com/kaililikai/p/5974506.html
Copyright © 2020-2023  润新知