zoukankan      html  css  js  c++  java
  • oracle 中批量数据的处理(转载)

    # FileName :oracle_pl/sql.txt
    # Write By : hgc 整理
    # Create Date : 2007-07-03
    # Last Modify : 2007-07-25
    # Description :介紹Oracle 10G pl/sql
    # source: 精通 oracle 10G  pl/sql 編程


    第三章 pl/sql基礎

    3.1
      pl/sql塊有三個組成部分﹐定義﹐執行﹐例外處理三部分。
     Declare
     /*
      * 定義部分﹐定義變量﹑常量﹑復雜數據類型﹑游標﹑例解
     */
     Begin
      /*
       * 執行部分 pl/sql語句和sql語句
       */
     Exception
      /*
       *例外處理部分 處理運行錯誤
       */  

    pl/sql塊分類﹕
       匿名塊﹑命名塊﹑子程序﹑觸發器
       子程序包括過程﹑函數﹑包

    3.2  定義和使用變量
     pl/sql的變形量類型﹐標量﹑復合類型﹑參照類型﹑lob類型
     標量類型﹕int﹑integer﹑number﹑date﹑boolean.....
     復合類型﹕record﹑table﹑varray
     參照類型﹕ref cursor﹑ref object_type
     lob類型 : bfile﹑blob﹑clob﹑nclob

       
    set serveroutput on
    --example 1  pl/sql record :
    declare
       type emp_record_type is record  (
        name   emp.ename%type,
        salary emp.sal%type,
        title  emp.job%type);
      emp_record emp_record_type;
     begin
      select ename,sal,job into emp_record
     from emp where empno = '7788';
     dbms_output.put_line('顧員名﹕'||emp_record.name);
     end;
      
      

    --example 2 pl/sql 表:
    declare
      type ename_table_type is table of emp.ename%type
       index by binary_integer;
      ename_table ename_table_type;
     begin
       select ename into ename_table(-1) from emp
         where empno=7788;
       dbms_output.put_line('顧員名﹕'||ename_table(-1));
     end;

    --example 3 參照變量
    Declare
      type c1 is ref cursor;
      emp_cursor c1;
      v_ename emp.ename%type;
      v_sal   emp.sal%type;
    begin
      open emp_cursor for
         select ename,sal from emp where deptno=10;
      LOOP
        Fetch emp_cursor into v_ename,v_sal;
        exit when emp_cursor%notfound;
        dbms_output.put_line(v_ename);
      END LOOP;
      close emp_cursor;
     end;    

    第四章 使用sql語句
     
    --exapmle 4 多表插入
     insert all
       when deptno=10 then into dept10
       when deptno=20 then into dept20
       when deptno=30 then into dept30
       when job='CLERK' then into clerk
       else into other
      select * from emp;
     
    --exapmle 5 使用FIRST操作符執行多表插入
     insert first
       when deptno=10 then into dept10
       when deptno=20 then into dept20
       when deptno=30 then into dept30
       when job='CLERK' then into clerk
       else into other
      select * from emp;

    4.4 數據分組

    --exapmle 6使用rollup操作
      select deptno,job,avg(sal) from emp
         group by rollup(deptno,job);


    --exapmle 7使用cube操作  
      select deptno,job,avg(sal) from emp
         group by cube(deptno,job);
        
    --exapmle 7使用grouping set
      select deptno,job,avg(sal) from emp    group by grouping sets(deptno,job);  


    --example等連接
     select e.ename,e.sal,d.dname from emp e,dept d
       where e.deptno=d.deptno;
      
    --example 不等連接  
      select a.ename,a.sal,b.grade from emp a,salgrade b
        where a.sal between b.losal and b.hisal;

    --example 自連接     
      select manager.ename from emp manager,emp worker
       where manager.empno=worker.mgr and worker.ename='BLAKE';

    --example 內連接        
     語法﹕
       select table1.column,table2.column
         from table1 [inner|left|right|full] join table2  table1.column=table2.column
        
     內連接
      select a.dname,b.ename from dept a,emp b
        where a.deptno=b.deptno and a.deptno=10;    
      
      select a.dname,b.ename from dept a inner join emp b
       on a.deptno=b.deptno and a.deptno=10; 
     在oracle9i中﹐如果主表的主鍵列和從表的外部鍵列名稱相同﹐那么可以使用natural join關
     鍵字自動執行內連接操作﹐
      select dname,ename from dept natural join emp;
     
      左外連接
      select a.dname,b.ename from dept a left join emp b
      on a.deptno=b.deptno and a.deptno=10;
     
        右外連接
      select a.dname,b.ename from dept a right join emp b
      on a.deptno=b.deptno and a.deptno=10;
     
      完全外連接
      select a.dname,b.ename from dept a full join emp b
      on a.deptno=b.deptno and a.deptno=10;
     
    --exapmle 8 多行子查詢
       in :匹配于子查詢結果的任一個值即可
       all:必須要符合子查詢結果的所有值。
       any 只要符合子查詢結果的任一個值即可
     
      in操作符
      select ename,job,sal deptno from emp where job in (select distinct job from emp where deptno=10);
     
      all操作符    
      select ename,job,sal deptno from emp where sal>all (select distinct sal from emp where deptno=30);

      any操作符    
      select ename,job,sal deptno from emp where sal>any (select distinct sal from emp where deptno=30);  
     
    --exapmle 9 case表達式
     select ename,sal, case
        when sal>3000 then 3
        when sal>2000 then 2
        else 1 end grade from emp ;
       
    --exapmle 9 with 表達式 ,只支持select  http://searchdatabase.techtarget.com.cn/tips/311/2607811.shtml  
      with summary as (
           select dname,sum(sal) as dept_total from emp,dept
             where emp.deptno=dept.deptno group by dname
            )
            select dname,dept_total from summary where dept_total>
            (select sum(dept_total)*1/3 from summary);
           
       WITH
            SEG AS (SELECT SEGMENT_NAME, SUM(BYTES)/1024 K FROM USER_SEGMENTS GROUP BY SEGMENT_NAME),
            OBJ AS (SELECT OBJECT_NAME, OBJECT_TYPE FROM USER_OBJECTS)
        SELECT O.OBJECT_NAME, OBJECT_TYPE, NVL(S.K, 0) SIZE_K
            FROM OBJ O, SEG S
        WHERE O.OBJECT_NAME = S.SEGMENT_NAME (+);
       
        WITH
           Q1 AS (SELECT 3 + 5 S FROM DUAL),
           Q2 AS (SELECT 3 * 5 M FROM DUAL),
           Q3 AS (SELECT S, M, S + M, S * M FROM Q1, Q2)
         SELECT * FROM Q3;       
       
    查看歷史數據
     AS OF子句可以查看過去的歷史數據(5分鐘之前的)
     select ename,sal from emp as of timestamp to_timestamp(
     '2003-05-18 19:59:00','YYYY-MM-DD HH24:MI:SS') WHERE ENAME='CLERK';
    使用dbms_flashback包獲取特定的scn的數據。
    exec dbms_flashback.enable_at_system_change_number(717402);
    select * from emp;
    exec dbms_flashback.disable;


    Declare
      v_deptno emp.deptno%type;
    Begin
      v_deptno :=&no;
      case v_deptno
        when 10 then
            update emp set comm=100 where deptno=v_deptno;
        when 20 then
            update emp set comm=80  where deptno=v_deptno;
        when 30 then
            update emp set comm=80  where deptno=v_deptno;
        else
            dbms_output.put_line('不存在該部門');
        end case;
      end;         

    Declare
      v_sal emp.sal%type;
      v_ename emp.ename%type;
    Begin
      select ename.sal into v_ename,v_sal from emp where empno=&no;
     Case
        when v_sal<1000 then
          update emp set comm=100 where ename=v_ename;
        when v_sal<2000 then
          update emp set comm=80 where ename=v_ename;   
        when v_sal<6000 then
          update emp set comm=50 where ename=v_ename;         
       end case;
      end;  


    --在values子句中使用記錄變量
    declare
      dept_record dept%rowtype;
      begin
      dept_record.deptno :=50;
      dept_record.dname :='asdfasdf';
      dept_record.loc :='asdfasdfsdf';
      insert into dept values dept_record;
    end; 


    --在set子句中使用記錄變量
    declare
      dept_record dept%rowtype;
      begin
      dept_record.deptno :=30;
      dept_record.dname :='sales';
      dept_record.loc :='asdfasdfsdf';
      update dept set row=dept_record where deptno=30;
    end;       

    在索引表中使用binary_integer和pls_integer
    set serveroutput on
    declare
       type  ename_table_type is table of emp.ename%type
        index by binary_integer;
        ename_table ename_table_type;
    begin
     select ename into ename_table(-1) from emp
      where empno=7788;
      dbms_output.put_line('雇員名:'||ename_table(-1));
     end;

    在索引表中使用varchar2 ,oracle9i才允許
    set serveroutput on
    declare
      type area_table_type is table of number
         index by varchar2(10);
      area_table area_table_type;
     begin
     area_table('北京') :=1;
     area_table('上海') :=2; 
     area_table('廣州') :=3; 
     dbms_output.put_line('第一個元素﹕'||area_table.first);
     dbms_output.put_line('最后一個元素﹕'||area_table.last);
    end;
       
    在pl/sql中使用嵌套表﹐
    declare
      type ename_table_type is table of emp.ename%type;
      ename_table ename_table_type;
     begin
      ename_table :=ename_table_type('MAY','MARY','MARRY');--這個必須要的﹐初始化動作
     SELECT ENAME INTO ENAME_TABLE(2) FROM EMP
      WHERE EMPNO=7788;
    DBMS_OUTPUT.PUT_LINE('雇員名﹕'|| ENAME_TABLE(2));
    end;

    在pl/sql中使用VARRAY
    DECLARE
       TYPE ename_table_type IS VARRAY(20) OF emp.ename%TYPE;
       ename_table ename_table_type :=ename_table_type('MARY'); --必須初始化
       begin
       select ename into ename_table(1) from emp
         where empno=7788;
        DBMS_OUTPUT.PUT_LINE('雇員名﹕'||ename_table(1) );
    END;

    pl/sql記錄表 多個欄位
    DECLARE
       TYPE emp_table_type is table of emp%ROWTYPE
          INDEX BY BINARY_INTEGER;
       emp_table emp_table_type;
     BEGIN
       SELECT * INTO emp_table(1) FROM emp
        WHERE empno=7788;
       dbms_output.put_line('雇員名﹕'||emp_table(1).ENAME);
       dbms_output.put_line('雇員名﹕'||emp_table(1).SAL);
    END;

    在pl/sql中多維varray
    DECLARE
    -- 一維定義
      TYPE AL_VARRAY_TYPE IS VARRAY(10) OF INT;
    -- 二維定義 
      TYPE nal_varray_type is VARRAY(10) OF al_varray_type;
    --初始化
      nal nal_varray_type :=nal_varray_type(
            al_varray_type(58,100,102),
            al_varray_type(55,6,73),
            al_varray_type(2,4));
    BEGIN
      FOR I in 1..nal.count LOOP
          FOR j in 1..nal(i).count LOOP
              DBMS_OUTPUT.PUT_LINE('NVL('||I||','||J||')='
              ||nal(i)(j));
          END LOOP;
       END LOOP;
     END;  

    --在pl/sql中使用多級嵌套表
    DECLARE
     --一級定義
       TYPE al_table_type IS TABLE OF INT;
     --二級定義
       TYPE nal_table_type IS TABLE OF al_table_type;
     --初始化
        nal nal_table_type :=nal_table_type(
              al_table_type(2,4),
              al_table_type(5,73));
        BEGIN
          FOR I IN 1..nal.count LOOP
             FOR J IN 1..nal(i).COUNT LOOP
              DBMS_OUTPUT.PUT_LINE('NVL('||I||','||J||')='
              ||nal(i)(j));
          END LOOP;
       END LOOP;
      END;  
     
     

    --在pl/sql中使用多級嵌套表類似多維數組
    DECLARE
     --一級定義
       TYPE al_table_type IS TABLE OF INT
         INDEX BY BINARY_INTEGER;
     --二級定義
       TYPE nal_table_type IS TABLE OF al_table_type
         INDEX BY BINARY_INTEGER;
        nal nal_table_type;
     --初始化
     BEGIN
        nal(1)(1) :=1;
        nal(1)(2) :=2;
        nal(2)(1) :=2;
        nal(2)(2) :=4;
        nal(1)(3) :=4;
     
          FOR I IN 1..nal.count LOOP
             FOR J IN 1..nal(i).COUNT LOOP
              DBMS_OUTPUT.PUT_LINE('NVL('||I||','||J||')='
              ||nal(i)(j));
          END LOOP;
       END LOOP;
      END;   

    --集合方法﹕
    集合方法是oracle提供用于操作集合變量的內置的函數和過程﹐exist,count,limit,first,next,prior和next是函數﹐
    extend,trim,delete則是過程。
    注意集合方法只用于pl/sql中﹐另外extend和trim只適于嵌套表和varray。而不適于索相表。

    1. EXISTS 用于確定集合元素的存在.
      Declare
        type ename_table_type is table of emp.ename%type;
        ename_table ename_table_type;
      Begin
        IF ename_table.exists('') then
           ename_table(1) :='scott';
        Else
           dbms_output.put_line('必須初始化');
        End if;
      End; 
    2. count 用于返回集合變量中的元素的總個數。如果元素個數為null,則統計不會包含。
      Declare
        Type ename_table_type is table of emp.ename%type
             index by binary_integer;
        ename_table ename_table_type;
      Begin
        ename_table(-5):='scott';
        ename_table(1):='ascott';
        ename_table(5):='sacott';
        ename_table(10):='sasdcott';
        ename_table(-8):='scotasdt';
        dbms_output.put_line('集合元素個數﹕'||ename_table.count);
      End;

    3. Limit 用于返回集合元素的最大個數﹐因嵌套表和索相表的個數沒有限制﹐
    所以返回null,對于varray則返回最大個數
       Declare
         type ename_table_type is varray(20) of emp.ename%type;
         ename_table ename_table_type :=ename_table_type('mary');
       Begin
          dbms_output.put_line('集合的最大個數﹕'||ename_table.limit);  
       End;
    4. First和Last
       First方用于返合集合變量的第一個元素的下標﹐相反Last則返回集合變量的最后一個元素的下標.
       Declare
         type ename_table_type is table of emp.ename%type
          index by binary_integer;
          ename_table ename_table_type;
        Begin
         ename_table(-5) :='adfadf-5';
         ename_table(1) :='adfadf1';
         ename_table(6) :='adfadf6';
         ename_table(10) :='adfadf10';
         ename_table(12) :='adfadf6';
         Dbms_output.put_line('第一個元素:'||ename_table.first);
         Dbms_output.put_line('最后一個元素:'||ename_table.last);
        End;   

     5. prior和next
        prior方法返回當前集合元素的前一個元素的下標﹐相反next返回當前集合元素的下一個元素的下標。
        Declare
            type ename_table_type is table of emp.ename%type
                  index by binary_integer;
             ename_table ename_table_type;
         Begin
          ename_table(-5) :='scott';
          ename_table(1) :='smith';
          ename_table(5) :='Mary';
          ename_table(10) :='scott';
          dbms_output.put_line('元素5的前一個元素﹕'||ename_table.prior(5));
          dbms_output.put_line('元素5的后一個元素﹕'||ename_table.next(5));    
         End;     
        
    6. extend
       該方法用于擴展集合變量的尺示﹐并為它增加元素﹐適用于嵌套表和varray.該方法有extend,extend(n)和extend(n,i)三種方式。
      其中extend用于為集合增加一個null元素﹐extend(n)則為集合增加n個null元素。extend(n,i)則為集合增加n個元素﹐元素值與第i個元素相同。
      Declare
         type ename_table_type is varray(20) of varchar2(10);
         ename_table ename_table_type;
         Begin
          ename_table :=ename_table_type('MARY');
          ename_table.extend(5,1);
          dbms_output.put_line('元數總個數﹕'||ename_table.count);
         end;
    7. trim
       該方法用于從集合尾部刪除元數﹐有trim和trim(n)兩種格式﹐trim用于從集合尾部刪除一個元素﹐
       而trim(n)用于從集合尾部刪除n個元素。該方法只適于嵌套表和varray.
       Declare
         type ename_table_type is table of varchar2(10);
         ename_table ename_table_type;
       Begin
         ename_table :=ename_table_type('A','A','A','A','A','A');
         ename_table.trim(2);
         dbms_output.put_line('元數總個數:'||ename_table.count);
       End;   
          
    8. Delete
       該方法用于刪除元素﹐只適用于嵌套表和索引表﹐而不適用varray.有delete,delete(n),delete(m,n)三種格式
       delete用于刪除所有元素﹐delete(n)刪除集合變量的第n個元素﹐而delete(m,n)用于刪除從m至n之間的所有元素﹐
       Declare
          type ename_table_type is table of emp.ename%type
           index by binary_integer;
          ename_table ename_table_type;
          Begin
            ename_table(-5) :='scotta';
            ename_table(1) :='scottb';
            ename_table(5) :='scottc';
            ename_table(10) :='scottd';
            ename_table.delete(5);
            dbms_output.put_line('元數總個數﹕'||ename_table.count);
          End;

    集合賦值 
         使用嵌套表和varray時﹐通過執行insert,update,fetch,select,賦值語句﹐用戶可以將一個集合的數據賦給另一個集合
      從oracle10G始﹐還可以用set,multiset union,multiset intersect,multiset except等集合操作符。
         set操作用于取消嵌套表中的重復值;
         multiset union 用于取得兩個嵌套表的并集(帶有distinct操作符可以取消重復結果)﹔     
         multiset intersect 用于取得兩個集合的交集﹔
         multiset except 用于取得兩個嵌套表的差集﹐

    1. 將一個集合的值賦給別一集合
    exp1
        Declare
          type name_varray_type is varray(4) of varchar2(10);
          name_array1 name_varray_type;
          name_array2 name_varray_type;    
        Begin
          name_array1 :=name_varray_type('scott','smith');
          name_array2 :=name_varray_type('a','a','a','a');
          dbms_output.put('name_array2的原數據﹕');
          for i in 1.. name_array2.count loop
             dbms_output.put_line(' '||name_array2(i));
          end loop;
          dbms_output.new_line;
          name_array2 :=name_array1;
          dbms_output.put('name_array2的新數據﹕');
          for i in 1.. name_array2.count loop
             dbms_output.put_line(' '||name_array2(i));
          end loop;
          dbms_output.new_line;
        End;     
    注意﹐當進行集合賦值時﹐源集合與目標集合的數據類型必須一致。如果集合元數數據類型一致﹐但集合類型不一致﹐也不能進行
    賦值﹐
    exp 錯誤的例子
       Declare
           type name_varray1_type is varray(4) of varchar2(10);
           type name_varray2_type is varray(4) of varchar2(10);
           name_array1 name_varray1_type;
           name_array2 name_varray2_type;
       Begin
         name_array1 :=name_varray1_type('scott','smith');
         name_array2 :=name_array1;
       End;   
      
    2.   給集合null值
       Declare
          type name_varray_type is varray(4) of varchar2(10);
          name_array name_varray_type;
          name_empty name_varray_type;
       Begin
        name_array :=name_varray_type('scott','smith');
        dbms_output.put_line('name_array原有元素的個數﹕'||name_array.count);
        name_array :=name_empty;
        IF name_array is null then
           dbms_output.put_line('name_array現有元素的個數﹕0');
        END IF;
       End;  
    3. 使用集合操作符給嵌套表賦值
      (1)使用Set操作符
       set 操作符用于取消特定嵌套表中的重復值﹐
        Declare
           type nt_table_type is table of number;
           nt_table nt_table_type :=nt_table_type(2,4,3,1,2);
           result nt_table_type;
        Begin
           result :=set(nt_table);
           dbms_output.put('result:');
           for i in 1..result.count loop
            dbms_output.put(' '||result(i));
           end loop;
           dbms_output.new_line;
        End; 
     (2) 使用multiset union操作符
         Declare
            type nt_table_type is table of number;
            nt1 nt_table_type :=nt_table_type(1,2,3);
            nt2 nt_table_type :=nt_table_type(3,4,5);
            result nt_table_type;
          Begin
            result :=nt1 multiset union nt2;
            dbms_output.put('result:');
            for i in 1..result.count loop
              dbms_output.put(' '||result(i));
            end loop;
            dbms_output.new_line;
          End; 

     (3) 使用multiset union distinct操作符
         Declare
            type nt_table_type is table of number;
            nt1 nt_table_type :=nt_table_type(1,2,3);
            nt2 nt_table_type :=nt_table_type(3,4,5);
            result nt_table_type;
          Begin
            result :=nt1 multiset union distinct nt2;
            dbms_output.put('result:');
            for i in 1..result.count loop
              dbms_output.put(' '||result(i));
            end loop;
            dbms_output.new_line;
          End;       

     (4) 使用multiset intersect操作符
         Declare
            type nt_table_type is table of number;
            nt1 nt_table_type :=nt_table_type(1,2,3);
            nt2 nt_table_type :=nt_table_type(3,4,5);
            result nt_table_type;
          Begin
            result :=nt1 multiset intersect nt2;
            dbms_output.put('result:');
            for i in 1..result.count loop
              dbms_output.put(' '||result(i));
            end loop;
            dbms_output.new_line;
          End;             

     (5) 使用multiset except操作符
         Declare
            type nt_table_type is table of number;
            nt1 nt_table_type :=nt_table_type(1,2,3);
            nt2 nt_table_type :=nt_table_type(3,4,5);
            result nt_table_type;
          Begin
            result :=nt1 multiset except nt2;
            dbms_output.put('result:');
            for i in 1..result.count loop
              dbms_output.put(' '||result(i));
            end loop;
            dbms_output.new_line;
          End;             


    比較集合
      從oracle10G開﹐開發人沒不僅可能檢查集合變量是否為null,還可以使用cardinality,submultiset of member of ,is a set, is empty等集合操作符﹐
      cardinality用于返回集合變量的元素的個數﹔
      submultiset of :用于確定一個嵌套表是否為另一嵌套表的子集﹔
      member of 用于檢測特定數據是否為嵌套表的元素﹔
      is a set 用于檢測嵌套表是否包含重復的元數值﹔
      is empty用于檢測是否為null﹐只適用于嵌套表而不適于varray;
     
      (1)檢測是否為null;
      Declare
         type name_array_type is array(3) of varchar2(10);
         name_array name_array_type;
      Begin
         if name_array is null then
            dbms_output.put_line('name_array 末初始化');
          end if; 
      End;
     
        Declare
         type name_array_type is table of varchar2(10);
         name_array name_array_type;
      Begin
         if name_array is empty then
            dbms_output.put_line('name_array 末初始化');
          end if; 
      End;
     
      (2)比較兩個嵌套表是否相同
       使用這兩相只能針對嵌套表﹐而不能是索引表和varray。
       Declare
          type name_table_type is table of varchar2(10);
          name_table1 name_table_type;
          name_table2 name_table_type;
       Begin
          name_table1 :=name_table_type('scott');
          name_table2 :=name_table_type('smith');
          if name_table1=name_table2 then
             dbms_output.put_line('兩個嵌套表完全相同');
          else
             dbms_output.put_line('兩個嵌套表數值不同');
          end if;
       End;

       (3) 在嵌套表中使用集合操作符(只適于嵌套表﹐不適行索引表和varray)
         1. cardinality 用于返回集合元數的個數
         Declare
           type nt_table_type is table of number;
           nt1 nt_table_type :=nt_table_type(1,2,3,4);
          Begin
            dbms_output.put_line('元數個數﹕'||cardinality(nt1));
          End;
         
          2.使用submultiset of
            用于確定一個嵌套表是否為另一嵌套表的子集﹐
            Declare
              type nt_table_type is table of number;
              nt1 nt_table_type :=nt_table_type(1,2,3);
              nt2 nt_table_type :=nt_table_type(1,2,3,4);
            Begin
              if nt1 submultiset of nt2 then
                dbms_output.put_line('nt1 是nt2的子集');
              end if;
            End;
           
            3. 使用操作符member of
              用于檢測特定數據是否為嵌套表的元素。
             Declare
                type nt_table_type is table of number;
                nt1 nt_table_type :=nt_table_type(1,2,3,5);
                v1 number :=1;
              Begin
                if v1 member of nt1 then
                   dbms_output.put_line('v1 是nt1的元素');
                end if;
              End;
           
            4. 使用is a set
              用于檢測嵌套表是否包含重復的元數值﹐
             Declare
               type nt_table_type is table of number;
               nt1 nt_table_type :=nt_table_type(1,2,3,5);
             Begin
                if nt1 is a set then
                 dbms_output.put_line('嵌套表nt1沒有重復值');
                end if;
             End;  


    8.3 批量綁定        
      為9i所新增特性
      create table demo(
         id number(6) primary key,
         name varchar2(10)
       ); 
      
       exp1 不使用批量綁定處理
        Declare
           type id_table_type is table of number(6)
              index by binary_integer;
           type name_table_type is table of varchar2(10)
             index by binary_integer;
           id_table id_table_type;
           name_table name_table_type;
           Start_time number(10);
           end_time number(10);           
        Begin
           for i in 1 ..5000 loop
             id_table(i) :=i;
             name_table(i) :='Name'|| to_char(i);
           end loop;
           start_time :=dbms_utility.get_time;
           for i in 1..id_table.count loop
            insert into demo values( id_table(i),name_table(i));
           end loop;
           end_time :=dbms_utility.get_time;
           dbms_output.put_line('總計時間(秒)﹕'||
             to_char((end_time-start_time)/100));
        End;
        exp2 使用批量綁定
        Declare
           type id_table_type is table of number(6)
              index by binary_integer;
           type name_table_type is table of varchar2(10)
             index by binary_integer;
           id_table id_table_type;
           name_table name_table_type;
           Start_time number(10);
           end_time number(10);           
        Begin
           for i in 1 ..5000 loop
             id_table(i) :=i;
             name_table(i) :='Name'|| to_char(i);
           end loop;
           start_time :=dbms_utility.get_time;
           forall  i in 1..id_table.count
            insert into demo values( id_table(i),name_table(i));
           end_time :=dbms_utility.get_time;
           dbms_output.put_line('總計時間(秒)﹕'||
             to_char((end_time-start_time)/100));
        End;   
       結論﹐批量綁定效果明顯優于不使用批量綁定﹐批量綁定使用bulk connect子句和forall語句來完成﹐其中bulk connect 來取得批量數據﹐
       該子句只能用于select 語句﹐fetch語句和dml返回子句中;而forall只適于執行批量綁定的dml操作。
    8.3.1 forall語句  
       當要在pl/sql應用程序執行insert,delete,update操作時﹐可以使用forall語句﹐在9i時﹐必須具有連續的元素﹐從10G開始﹐通過使用新增加的indices of 子句和values of子句
       可以使用連續的集合元素。從10G開始有三種執行方法
        語法一﹕
          Forall index in lower_bound ..upper_bound
             sql_statement;
        語法二﹕
        forall index in indices of collection
           [between lower_bound and upper_bound]
           sql_statement;
        語法三﹕
         forall index in values of index_collection
           sql_statement;
         
         1.在insert 語句上使用批量綁定變量
           Declare
              type id_table_type is table of number(6)
                 index by binary_integer;
              type name_table_type is table of varchar2(10)
                 index by binary_integer;
              id_table id_table_type;
              name_table name_table_type;
            Begin
              for i in 1..10 loop
               id_table(i) :=i;
               name_table(i) :='name'||to_char(i);
              end loop;
              forall i in 1..id_table.count
                insert into demo values(id_table(i),name_table(i));
            End;    
         2. 在update 語句上使用批量綁定           
           Declare
              type id_table_type is table of number(6)
                 index by binary_integer;
              type name_table_type is table of varchar2(10)
                 index by binary_integer;
              id_table id_table_type;
              name_table name_table_type;
            Begin
              for i in 1..5000 loop
               id_table(i) :=i;
               name_table(i) :='N'||to_char(i);
              end loop;
              forall i in 1..id_table.count
                update  demo set name=name_table(i)
                  where id=id_table(i);
            End;             
         3. 在delete語句上使用批量綁定
           Declare
              type id_table_type is table of number(6)
                 index by binary_integer;
              id_table id_table_type;
            Begin
              for i in 1..5000 loop
               id_table(i) :=i;
              end loop;
              forall i in 1..id_table.count
               delete from   demo      where id=id_table(i);
            End;             
         4. 在forall語句中使用部分批量綁定
                 Declare
              type id_table_type is table of number(6)
                 index by binary_integer;
              id_table id_table_type;
            Begin
              for i in 1..10 loop
               id_table(i) :=i;
              end loop;
              forall i in 8..10
               insert into  demo (id) values (id_table(i));
            End;              
          5. 在forall語句上使用indices of子句。
           Declare
              type id_table_type is table of number(6);
              id_table id_table_type;
            Begin
              id_table :=id_table_type(1,null,3,null,5);
              forall i in indices of id_table
               delete demo where id=id_table(i);
            End;         
          6. 在forall語句上使用values of子句 --例子有誤。。。
           values of子句是10G新增的功能﹐用于從集合變量中取得集合下標(index)的值﹐
           create table new_demo as select * from demo where 'a'='b';
          
           Declare 
             type id_table_type is table of demo.id%type;
             type name_table_type is table of demo.name%type;
             id_table id_table_type;
             name_table name_table_type;
             type index_pointer_type is table of pls_integer;
             index_pointer index_pointer_type;
           Begin
             select * bulk collect into id_table,name_table from demo;
             index_pointer :=index_pointer_type(2,4,6);
             --forall i in values of index_pointer     --錯誤的
                --insert into new_demo values(id_table(i),name_table(i));  --錯誤的
             forall i in id_table.first ..id_table.last
               insert into new_demo values(id_table(i),name_table(i));
           End;


    8.3.2 BULK CONNECT子句
        bulk connect 子句用于取得批量數據﹐適用于select into﹐fetch into,和dml返回語句。可以將批量數據放在pl/sql集合孿量中﹐
        語法﹕bulk connect into collection_name[,connect_name]...
       
        1. 在select into語句中使用bulk connect子句
           Declare
              type emp_table_type is table of emp%rowtype
                 index by binary_integer;
              emp_table emp_table_type;   
           Begin
              select * bulk collect into emp_table from emp;
              for i in 1..emp_table.count loop
                 dbms_output.put_line('顧員姓名'||emp_table(i).ename);
              end loop;
           End;
        2. 在dml的返回語句中使用bulk collect子句
           Declare
              type ename_table_type is table of emp.ename%type;
              ename_table ename_table_type;
            Begin
               delete from emp where dempno=&no
                 Return ename bulk collect into ename_table;
               for i in 1..ename_table.count loop
                  dbms_output.put(ename_table(i)||' '); 
               end loop;
               dbms_output.new_line;
            End;
          
          
        第9章 使用游標      

    9.1 顯示游標
      1. 使用顯示游標
                                 |----|
           Declare -->Open -->Fetch -->空-->close
         (1)定義游標
             Cursor cursor_name is select_statement;
         (2)打開游標
             open cursor_name;
         (3)提取數據
             語法一: fetch cursor_name into vari1,vari2....;
             語法二: fetch cursor_name
                        bulk collect into collect1,collect2....[limit rows];      
         (4)關閉游標
         close cursor_name;               
     
      2. 顯示游標屬性(%isopen﹑%found﹑%notfound﹑%rowcount)
         當使用顯式游標時﹐必須要在顯示游標屬性之前帶有顯示游標的名樂作前綴(游標名.屬性名)
         exp1:
         Declare
           Cursor emp_cursor is
               select ename,sal from emp where deptno=10;
               v_ename emp.ename%type;
               v_sal emp.sal%type;
         Begin
            open emp_cursor;
            Loop
             Fetch emp_cursor into v_ename,v_sal;
             exit when emp_cursor%notfound;
             dbms_output.put_line(v_ename||': '||v_sal);
            End loop;
         close emp_cursor;
         End;
        
         exp2:
       
             Declare
           Cursor emp_cursor is
               select ename from emp where deptno=10;
            Type ename_table_type is table of varchar2(10);
            ename_table ename_table_type;
         Begin
            open emp_cursor;
            Fetch emp_cursor bulk collect into ename_table;
            for i in 1..ename_table.count loop
               dbms_output.put_line(ename_table(i));
            End loop;
         close emp_cursor;
         End;
        
         exp3:在顯示游標中使用fetch ...bulk connect into ..limit語句提取部分數據
          當使用fetch ...bulk connect into ..limit語句提數據時﹐默認為全部﹐如果結果集有大量數據
          并且使用varray集合變量接收數據﹐那么必須限定每次提取行數。
         Declare
           type name_array_type is varray(5) of varchar2(10);
           name_array name_array_type;
           cursor emp_cursor is select ename from emp;
           rows int :=5;
           v_count int :=0;
         Begin
           open emp_cursor;
           Loop
             fetch emp_cursor bulk collect into name_array limit rows;
              dbms_output.put('顧員名﹕');
             for i in 1..(emp_cursor%rowcount-v_count) loop
               dbms_output.put(name_array(i)||'  ');
             end loop;
             dbms_output.new_line;
             v_count :=emp_cursor%rowcount;
             exit when emp_cursor%notfound;
     --         dbms_output.put_line(emp_cursor%rowcount);
           End Loop;
           close emp_cursor;    
         End;  
        
         exp4:使用游標屬性
           Declare
               Cursor emp_cursor is
                  select ename from emp where deptno=10;
               type ename_table_type is table of varchar2(10);
               ename_table ename_table_type;
            Begin
               if not emp_cursor%isopen then --not open cursor
                  open emp_cursor;
               end if;
               fetch emp_cursor bulk collect into ename_table;
               dbms_output.put_line('提取的總計數﹕'||emp_cursor%rowcount);
               close emp_cursor;
            End;   
           
          exp5: 基于游標變量的記錄孌量
            Declare
               cursor emp_cursor is select ename,sal from emp;
               emp_record emp_cursor%rowtype;
            Begin
               open emp_cursor;
               Loop
                  Fetch emp_cursor into emp_record;
                  exit when emp_cursor%notfound;
                  dbms_output.put_line('顧叫名﹕'||emp_record.ename||'顧員工資:'||emp_record.sal);
               end loop; 
            close emp_cursor;
            End;

    9.2 參數游標
       語法﹕
          cursor cursor_name (parameter_name datatype) is select _statement;
        exp:
         declare
             cursor emp_cursor(no number) is
               select ename from emp where deptno=no;
             v_ename emp.ename%type;
          Begin
            open emp_cursor(10);
            Loop
              fetch emp_cursor into v_ename;
              exit when emp_cursor%notfound;
              dbms_output.put_line(v_ename);
            End loop;
          close emp_cursor;
          End;  

    9.3 使用游標更新或刪除數據       
       1. 使用游標更新數據
        Declare
           Cursor emp_cursor is
            select ename,sal from emp for update;
            v_ename emp.ename%type;
            v_oldsal emp.sal%type;
         Begin
           open emp_cursor;
           Loop
              fetch emp_cursor into v_ename,v_oldsal;
              exit when emp_cursor%notfound;
              if v_oldsal<2000 then
                 update emp set sal=sal+100 where current of emp_cursor;
               end if;      
           End loop;
           close emp_cursor;
         End;
        
        2. 使用游標刪除數據
          Declare
              cursor emp_cursor is
                 select ename,sal,deptno from emp for update;
              v_ename emp.ename%type;
              v_oldsal emp.sal%type;
              v_deptno emp.deptno%type;
          Begin      
            open emp_cursor;
            Loop
               fetch emp_cursor into v_ename,v_oldsal,v_deptno;
                   exit when emp_cursor%notfound;
               if v_deptno=30 then
                  delete from emp where current of emp_cursor;
               end if;
             end loop;
             close emp_cursor; 
          End;
         
        3. 使用of子句在特定表上加行共享鎖
        為了只在特定的表上加行共享鎖﹐需要在for update子句后面帶of子句.
          Declare
            cursor emp_cursor is
               select ename,sal,dname,emp.deptno from emp,dept
                  where emp.deptno=dept.deptno for update of emp.deptno;
             emp_record emp_cursor%rowtype;
          Begin  
            open emp_cursor;
            loop
              fetch emp_cursor into emp_record;
              exit when emp_cursor%notfound;
              if emp_record.deptno=30 then
                 update emp set sal=sal+100 where current of emp_cursor;
               end if;
               dbms_output.put_line('顧員名:'||emp_record.ename||'  工資﹕'||emp_record.sal
               ||'  部門﹕'||emp_record.dname);
            end loop;
          close emp_cursor;
          End;
         
          4.使用nowait子句
             使用for update語句對被作用行加鎖﹐如果其他會話已經在被作用行上加鎖﹐那么在默認情況下則一直等待。
             通過在for update子句中指定nowait語句﹐可以避免等待﹐當指定了nowait子句之后﹐如果其它會話已在被作用行上加鎖﹐則
             會報錯。

    9.4 游標for循環
       當使用游標for循環時﹐oracle會隱含的打開游標﹐提取游標數據并關閉游標。
       for record_name in cursor_naem loop
          statement1
          statement2
          .....
       emd loop; 
      
       1. 使用游標for循環
        Declare
          cursor emp_cursor is select ename,sal from emp;
        Begin
          for emp_record in emp_cursor loop
             dbms_output.put_line('第'||emp_cursor%rowcount||'個顧員﹕'||emp_record.ename);
          end loop;
        End; 
      
       2. 在游標for循環中直接使子查詢
       Begin
         for emp_record in (select ename,sal from emp) loop
           dbms_output.put_line(emp_record.ename);
         end loop;     
       end;   


    9.5 使用游標變量
     1. 游標變量使用步驟
      (1)定義ref cursor類型和游標變量
         type ref_type_naem is ref cursor [return return_type];
         cursor_variable ref_type_name;
       (2)打開游標
          open cursor_variable for select-statement;
       (3)提取游標數據 
          語法一﹕fetch cursor_variable into variable1,variable2....;
          語法二﹕fetch cursor_variable bulk collect into collect1,collect2...[limit rows];
       (4)關閉游標變量
          close cursor_variable;
      2:游標變量示例
        exp1:
         Declare
           type emp_cursor_type is ref cursor;
           emp_cursor emp_cursor_type;
           emp_record emp%rowtype;
         Begin
           open emp_cursor for select * from emp where deptno=10;
           Loop
             fetch emp_cursor into emp_record;
             exit when emp_cursor%notfound;
             dbms_output.put_line('第'||emp_cursor%rowcount||'個顧員:'||emp_record.ename);
           End loop;
           close emp_cursor;
         End;        
       
        exp2: 在定義ref cursor類型時指定return子句
         Declare
           type emp_record_type is record(
              name varchar2(10),salary number(6,2));
           type emp_cursor_type is ref cursor return emp_record_type;
           emp_cursor emp_cursor_type;
           emp_record emp_record_type;
         Begin
           open emp_cursor for select ename,sal from emp where deptno=10;
           Loop
             fetch emp_cursor into emp_record;
             exit when emp_cursor%notfound;
             dbms_output.put_line('第'||emp_cursor%rowcount||'個顧員:'||emp_record.name);
           End loop;
           close emp_cursor;
         End;        

    9.6 使用cursor表達式
        cursor表達式是oracle9i的新增加的特性。用于返回嵌套游標﹐
        exp:
         Declare
           type refcursor is ref cursor;
           cursor dept_cursor(no number) is
              select a.dname,cursor(select ename,sal from emp where deptno=a.deptno)
                  from dept a where a.deptno=no;
           empcur refcursor;
           v_dname dept.dname%type;
           v_ename emp.ename%type;
           v_sal   emp.sal%type;
         Begin
           open dept_cursor(&no);
           Loop
             Fetch dept_cursor into v_dname,empcur;
             exit when dept_cursor%notfound;
             dbms_output.put_line('部門名:'||v_dname);
             Loop
                fetch empcur into v_ename,v_sal;
                exit when empcur%notfound;
               dbms_output.put_line('顧員名:'||v_ename||' 工資﹕'||v_sal);
             End loop;
           End loop;
           close dept_cursor;
         End;     

    第十章 例外處理
    ....
    ....

    10.3 處理非預定義例外
         定義例外----->關聯例外和錯誤------>引用例外
         Declare
            e_integrity exception;
            pragma exception_init(e_integrity,-2291);
         Begin
            update emp set deptno=&dno where empno=&empno;
         Exception
            when e_integrity then
              dbms_output.put_line('該部門不存在');
         End; 
        
    10.4 處理自定義例外
         自定義例外必須顯示觸發。
         定義例外------>顯示觸發例外------->引用例外
         Declare
            e_integrity exception;
            pragma exception_init(e_integrity,-2291);
            e_no_employee exception;
         Begin
            update emp set deptno=&dno where empno=&empno;
            if sql%notfound then
              raise e_no_employee;
            end if;
         Exception
            when e_integrity then
              dbms_output.put_line('該部門不存在');
            when e_no_employee then
              dbms_output.put_line('該顧員不存在');
         End;    


    10.5 使用例外函數
       1. sqlcode和sqlerrm
         undef v_sal
         Declare
            v_ename emp.ename%type;
         Begin
           select ename into v_ename from emp where sal=&&v_sal;
           dbms_output.put_line('顧員名:'||v_ename);
         Exception
           when no_data_found then
             dbms_output.put_line('不存在工資料'||&v_sal||'的顧員');
           when others then
            dbms_output.put_line('錯誤號是:'||sqlcode);
            dbms_output.put_line(sqlerrm);
         End;
       
        2. raise_application_error
           raise_application_error(error_number,message,[{true|false}]);
          Create or replace procedure raise_comm
            (eno number,commission number)
          Is
             v_comm emp.comm%type;
           Begin
             select comm into v_comm from emp where empno=eno;
             if v_comm is null then
               Raise_application_error(-20001,'該顧員無補助');
             end if;
           Exception
             when no_data_found then
               dbms_output.put_line('該顧員不存在');
           End; 

    10.6 pl/sql 編譯警告
         從oracle10G開始﹐為提高pl/sql子程序的健康壯性并避免錯誤﹐在編譯pl/sql子程序之前開發人員
         可激活警告檢查。
         1. pl/sql警告分類
           Server:用于檢查妯現不可預料的結果或錯誤的結果。如參數的別名問題
           performance:用于檢查可能引起的性能問題﹐如insert操作為number提供了varchar2的數據。
           informational: 用于檢查子程序中的死代碼。
           all:用于檢查所有警告
         2. 控制pl/sql警告信息
          sql> alter system set plsql_warnings='ENABLE:ALL'; 
          sql> alter session set plsql_warnings='enable:performance';
          sql> alter procedure hello_compile plsql_warnings='enable:performance';
          sql> alter session set plsql_warnings='disable:all';
          sql> alter session set plsql_warnings='enable:server','disable:performance','error:06022';
          sql> call dbms_warning.set_warning_setting_string('ENABLE:ALL','SESSION');

    第十一章 開發子程序
    .....
    .....
    第十四章 開發動態sql
    14.1 動態sql簡介
     1. 靜態sql
       指直接嵌入在pl/sql塊中的sql語句。用于完成特定的或固定的任務。
       exp:
        select ename,sal into v_ename,v_sal from emp where empno=v_empno;
        insert into emp(empno,ename,sal) valeus(v_empno,v_ename,v_sal);
        update emp set sal=v_sal where ename=v_ename;
        delete from emp where empno=v_empno;
      上四條都是靜態sql,用于完成指定的任務
     
     2.動態sql  
       指在運行pl/sql塊時動態輸入的sql語句﹐如果要在pl/sql塊中執行ddl語句(如create,alter ,drop語句)﹑dcl語句(grant,revoke)或者里面果執行
       更回靈活的sql語句(如select語句中不同的where條件)﹐那就必須是動態sql,
     
     3. 靜態sql與動態sql比較
       靜態sql在編寫pl/sql塊時直接嵌入的sql語句﹐而動態sql是在運行pl/sql塊是動態輸入的語句。
       靜態sql性能要優于動態sql,因此在編寫pl/sql塊是﹐如功能完全確定則使用靜態sql,不確定則使用動態sql.
     
     4. 動態sql的處理方法
       當編寫動態sql時﹐根據要處理sql句的不同﹐可以使用三種不同的動態sql方法
       (1) 使用execute immediate 語句
            execute immediate 語句可以處理多數動態sql操作﹐但不能處理地多行查詢語句。
       (2)使用open-for,fetch和close語句    
           為了處理動態的多行查詢﹐必須使用open-for語句來打開游標﹐用用fetch循環取數據然后close關閉
       (3) 使用批量動態sql

    14.2 處理非查詢語句
       語法﹕Execute immediate dynamic_string
       [into {define_variable[,define_variable]...|record}]
       [using [in|out|in out] bind_argument
       [,[in|out| in out]bind_argument]....]
       [{returning | return} into bind_argument[,bind_argument]...];
      
       1.使用 execute immediate 處理ddl操作
         exp:
         create or replace procedure drp_table(table_name varchar2)
         is
           sql_statement varchar2(100);
         Begin
          sql_statement :='drop table '||table_name;
          execute immediate sql_statement;
         End; 

       2.使用 execute immediate 處理dcl操作
         exp:
         create or replace procedure grant_sys_priv(priv varchar2,usernaem varchar2)
         is
           sql_stat varchar2(100);
         Begin
          sql_statement :='grant  '||priv ||' to '||username;
          execute immediate sql_stat;
         End;      
     
       3. 使用execute immediate 處理dml操作
        
         (1) 處理無占位符和returning的dml語句
             Declare
                sql_stat varchar2(100);
             Begin
                 sql_stat :='update semp set sal=sal*1.1 where deptno=30';
                 execute immediate sql_stat;
             End;      
           
            (2)處理包含占位符的dml語句
               Declare
                  sql_stat varchar2(100);
               Begin
                 sql_stat :='update emp set sal=sal*(1+:percent/100)'
                 || ' where deptno=:dno';
                 execute immediate sql_stat using &1,&2;
               End;  
            (3)處理包含returning子句的dml語句(只處理單行)
              Declare
                  salary number(6,2);
                  sql_stat varchar2(100);
               Begin
                 sql_stat :='update emp set sal=sal*(1+:percent/100)'
                 || ' where empno=:dno returning sal into :salary';
                 execute immediate sql_stat using &1,&2
                  returning into salary;
                  dbms_output.put_line('新工資﹕'||to_char(salary));
               End;           
             
               Declare
                  sql_stat varchar2(400);
                  v_empno emp.empno%type;
                  v_ename emp.ename%type;
                  v_deptno   emp.deptno%type;
               Begin
                sql_stat :='insert into  emp(empno,ename,deptno) values(:empno,:ename,:deptno) returning empno,ename,deptno into:v_empno,:v_ename,:v_deptno';
                 execute immediate sql_stat using &1,&2,&3 returning into v_empno,v_ename,v_deptno;
                  dbms_output.put_line('新工資﹕'||to_char(v_empno));
               End;           
            (4)使用execute immediate處理單行記錄
              Declare
                  sql_stat varchar2(100);
                  emp_record emp%rowtype;
               Begin
                 sql_stat :='select * from emp where empno =:eno';
                 execute immediate sql_stat  into emp_record using &i;
                 dbms_output.put_line('顧員'|| emp_record.ename || '的工資為' || emp_record.sal);
               End;                      
              
    14.3處理多行查詢
       為了處理select語句返回的多行數據﹐需要使用open_for,fetch和close語句﹐
       定義游標變量--->打開游標變量---->循環提取數據----->關閉游標變量
      
       1. 定義游標變量
           type cursortype is ref cursor;
           cursor_variable cursortype;
       2. 打開游標變量
          open cursor_variable for dynamic_straint
          [using bind_argument[,bind_argumen1...];
       3. 循環提取數據
          Fetch cursor variable into {var1[var2]....|record_var];
       4. 關閉游標變量
          close cursor_variable;
       5. 多行查詢示例
       Declare
         Type empcurtype is ref cursor;
         emp_cv empcurtype;
         emp_record emp%rowtype;
         sql_stat varchar2(300);
       Begin
         sql_stat :='select * from emp where deptno=:dno';
         open emp_cv for sql_stat using &do;
         Loop
            fetch emp_cv into emp_record;
            exit when emp_cv%notfound;
            dbms_output.put_line('顧員名:'|| emp_record.ename||'工資:'||emp_record.sal);
         End loop;
         close emp_cv;
       End;          
                        
    14.4 在動態sql中使用bulk子句
         1. 在execute immediate 語句中命名用動態bulk子句
         語法﹕execute immediate dynamic_string
          [bulk collect into define_variable[,define_variable...]]
          [using bind_argument[,bind_argument ....]]
          [{returning|return}
            bulk collect into return_variable[,return_variable...]];
          (1)使用bulk子句處理dml語句返回子句
             Declare
               Type ename_table_type is table of emp.ename%type
                 index by binary_integer;
               type sal_table_type is table of emp.sal%type
                 index by binary_integer;
               ename_table ename_table_type;
               sal_table sal_table_type;
               sql_stat varchar2(400);
             Begin
               sql_stat :='update emp set sal=sal*(1+:percent/100) where deptno=:dno'
               ||' returning ename,sal into :name,:salary';
               execute immediate sql_stat using &percent,&dno returning bulk collect into ename_table,sal_table;
               for i in 1..ename_table.count loop
                 DBms_output.put_line('顧員﹕'||ename_table(i)||'工資料﹕'||sal_table(i));
               end loop;
             End;   
                
            (2)使用bulk子句處理多行查詢
              Declare
                type ename_table_type is table of emp.ename%type
                    index by binary_integer;
                ename_table ename_table_type;
                sql_stat varchar2(100);
             Begin
                sql_stat :=' select ename from emp where deptno=:dno';
                execute immediate sql_stat
                  bulk collect into ename_table using &dno;
                For i in 1.. ename_table.count loop
                  dbms_output.put_line(ename_table(i));
                End loop; 
             End;       
                
        2. 在fetch語句中使用bulk子句
           Declare
                type empcurtype is ref cursor;
                emp_cv empcurtype;
                type ename_table_type is table of emp.ename%type
                    index by binary_integer;
                ename_table ename_table_type;
                sql_stat varchar2(200);
             Begin
                sql_stat :=' select ename from emp where job=:titiel';
                open emp_cv for sql_stat using '&job';
                fetch emp_cv bulk collect into ename_table;
                For i in 1.. ename_table.count loop
                  dbms_output.put_line(ename_table(i));
                End loop;
                close emp_cv; 
             End;       

        3. 在forall語句中使用bulk子句
           forall index in lower bound ...upper bound
              execute immediate dynamic_straing
              using bind_argument|bind_argument(index)
             [,bind_argument|bind_argument(index)].....
             [{returning|return } bulk collect into bind_argument[,bind_arguent...]];        
                
             Declare
               type ename_table_type is table of emp.ename%type;
               type sal_table_type is table of emp.sal%type;
               ename_table ename_table_type;
               sal_table   sal_table_type;
               sql_stat varchar2(200);
             Begin
               ename_table :=ename_table_type('SCOTT','SMITH','CLARK');
               sql_stat :='update emp set sal=sal*1.1 where ename=:1 returning sal into :2';
               forall i in 1..ename_table.count
                 execute immediate sql_stat using ename_table(i)
                 returning bulk collect into sal_table;
                 for j in 1..ename_table.count loop
                   dbms_output.put_line('顧員:'||ename_table(j)||'的新工資料'||sal_table(j));
                 end loop;
             End; 

    转自:http://blog.chinaunix.net/u/20571/showart_347237.html

  • 相关阅读:
    SharePoint部署webpart时候,报错:部署步骤“回收 IIS 应用程序池”中出现错误: 无效命名空间 解决方案
    免费的分布式的自动化测试工具
    https://github.com/dotnetcore
    SharePoint2013与SharePoint2016语言切换原理以及如何使用代码进行语言切换
    微软开源最强Python自动化神器Playwright!不用写一行代码!
    B站播单按时间统计进度
    AF_INET与PF_INET的区别
    git显示:fatal: index file smaller than expected
    Unix系统中信号SIGKILL和SIGSTOP
    GTM、UTC和C/C++中的时间处理
  • 原文地址:https://www.cnblogs.com/dooom/p/1820826.html
Copyright © 2011-2022 走看看