隨筆-314  評論-209  文章-0  trackbacks-0

          這段代碼同樣是執行了1000條insert語句,但是每一條語句都是不同的,因此ORACLE會把每條語句硬解析一次,其效率就比前面那段就低得多了。如果要提高效率,不妨使用綁定變量將循環中的語句改為

                sqlstr:='insert into 測試表 (:i,:i+1,:i*1,:i*2,:i-1) ';

                execute immediate sqlstr using i,i,i,i,i;

          這樣執行的效率就高得多了。

          我曾試著使用綁定變量來代替表名、過程名、字段名等,結果是語句錯誤,結論就是綁定變量不能當作嵌入的字符串來使用,只能當作語句中的變量來用。

          從效率來看,由于oracle10G放棄了RBO,全面引入CBO,因此,在10G中使用綁定變量效率的提升比9i中更為明顯。

          最后,前面說到綁定變量是在通常情況下能提升效率,那哪些是不通常的情況呢?

          答案是:在字段(包括字段集)建有索引,且字段(集)的集的勢非常大(也就是有個值在字段中出現的比例特別的大)的情況下,使用綁定變量可能會導致查詢計劃錯誤,因而會使查詢效率非常低。這種情況最好不要使用綁定變量。

           

           

           

           

           

           

           

          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比以前可能用到的更容易并且更高效.當意圖執行動態語句時,適當地處理異常更加重要.應該關注于捕獲所有可能的異常.

          posted on 2010-11-01 14:42 xzc 閱讀(963) 評論(0)  編輯  收藏 所屬分類: Oracle
          主站蜘蛛池模板: 新巴尔虎右旗| 织金县| 肇庆市| 沁水县| 靖西县| 武乡县| 南江县| 沧源| 天等县| 余江县| 正阳县| 申扎县| 新龙县| 安溪县| 宜阳县| 晋中市| 文山县| 沽源县| 满洲里市| 宝应县| 湄潭县| 望江县| 克拉玛依市| 景德镇市| 郎溪县| 环江| 凤山县| 阿拉善右旗| 黎城县| 南溪县| 绥滨县| 蓬溪县| 宣化县| 蓬莱市| 青河县| 五河县| 武平县| 耒阳市| 华宁县| 祁连县| 江华|