少年阿賓

          那些青春的歲月

            BlogJava :: 首頁 :: 聯系 :: 聚合  :: 管理
            500 Posts :: 0 Stories :: 135 Comments :: 0 Trackbacks
           CREATE OR REPLACE PROCEDURE INSERTAMOUNTTEST
          (
          ST_NUM        IN     NUMBER,
          ED_NUM        IN     NUMBER
          )
          IS
          BEGIN
          declare
                 i   number;
          begin
          FOR i IN ST_NUM..ED_NUM LOOP
          INSERT INTO tb values(i,i,'3','3','3',100,'0');
          END LOOP;
          end;
          END;

          運行:
          sql>execute INSERTAMOUNTTEST(1,45000)   -- 一次插入45000條測試數據

          2、從存儲過程中返回值
          create or replace procedure spaddflowdate
          (
          varAppTypeId               in varchar2,
          varFlowId                  in varchar2,
          DateLength                 in number,
          ReturnValue                out number    --返回值
          )
          is
          begin
          insert into td values(varAppTypeId,varFlowId,DateLength)
          returning 1 into ReturnValue;   --返回值
          commit;
          exception
          when others then
          rollback;
          end;

          存儲過程的執行
          sql>variable testvalue  number;
          sql>execute spaddflowdate('v','v',2,:testvalue);
          sql>print
          就可以看到執行結果

           

          3、用包實現存儲過程返回游標:
          create  or  replace  package  test_p 
          as 
           
          type  outList  is  ref  cursor; 
           
          PROCEDURE  getinfor(taxpayerList  out  outList); 
           
          end  test_p; 


          create  or  replace  package  body  test_p  as  PROCEDURE  getinfor(taxpayerList out  outList)  is  begin 
                OPEN  taxpayerList    FOR  select  *  from
                                  td where tag='0'; 
           
          end  getinfor; 
           
          end  test_p; 

           
           
           
          運行:
           
          set  serverout  on;    --將輸出工具打開
           
          variable  x  refcursor; 
           
          execute test_p.getinfor(:x);

          exec  test_p.getinfor(:x);
           
          print  x; 


          drop package test_p;

           

           

           

          /*procedural language/sql*/
          --1、過程、函數、觸發器是pl/sql編寫的
          --2、過程、函數、觸發器是在oracle中的
          --3、pl/sql是非常強大的數據庫過程語言
          --4、過程、函數可以在java程序中調用

          --提高效率:優化sql語句或寫存儲過程
          --pl/sql移植性不好

          --IDE(Integration Develop Environment)集成開發環境

          --命令規則:
          --變量(variable)           v_
          --常量(constant)           c_
          --指針、游標(cursor)         _cursor
          --例外、異常(exception)    e_

          --可定義的變量和常量:
            --標量類型:scalar
            --復合類型:composite    --存放記錄、表、嵌套表、varray
            --參照類型:reference
            --lob(large object)
           


          《PL/SQL 基本語法》

          --例:創建存儲過程
          create or replace procedure pro_add
          is
          begin
            insert into mytest values('韓xx','123');
          end;
          exec pro_add; --調用

          --查看錯誤信息
          show error;
          --調用過程
          exec 過程(c1,c2,...);
          call 過程(c1,c2,...);
          --打開/關閉輸出選項
          set serveroutput on/off
          --輸入
          &

          --塊結構示意圖
          declare   --定義部分,定義常量、變量、游標、例外、復雜數據類型
          begin     --執行部分,執行pl/sql語句和sql語句
          exception --例外處理部分,處理運行的各種錯誤
          end;      --結束


          --《實例演示》
          declare
            v_ival number(4) :=100; --聲明并初始化變量
            --v_dtm date;
            v_dtm syslogs.dtm%type; --取表字段類型
            v_content varchar(512);
          begin
            v_ival := v_ival * 90;  --賦值運算
            insert into syslogs values(seq_syslogs.nextval,10,sysdate,'v_ival='||v_ival,user);--數據庫存儲
            dbms_output.put_line('v_ival'||v_ival);
           
            select count(*) into v_ival from syslogs;--使用select查詢賦值
          --select ename,sal into v_name,v_sal from emp where empno=&aa;
            insert into syslogs values (seq_syslogs.nextval,10,sysdate,'日志條數='||v_ival,user);
            dbms_output.put_line('日志條數'||v_ival);
            
            --獲取日志序號==11的日志時間和日志內容
            select dtm , content
            into v_dtm,v_content
            from syslogs
            where logid=14;
           
            insert into syslogs values (seq_syslogs.nextval,'10',sysdate,'v_dtm='||v_dtm||'v_content='||v_content,user);
            dbms_output.put_line('v_dtm='||v_dtm||'v_content='||v_content);
            --修改日志序號=11的日志記錄人
            update syslogs
            set whois='PL/SQL.'||v_ival
            where logid = 14;
           
            --delete syslogs where logid=15;
           
            --分支流程控制
            if v_ival>50 then
              dbms_output.put_line('日志需要清理了~');
            else
              dbms_output.put_line('日志空間正常!');
            end if;
           
            --Loop循環
            v_ival :=0;
            loop
                exit when v_ival>3;
                     --循環體
                     v_ival := v_ival+1;
                     dbms_output.put_line('loop循環:'||v_ival);
            end loop;
           
            --While循環
            v_ival := 0;
            while v_ival < 4
            loop
               --循環體
               v_ival := v_ival+1;
               dbms_output.put_line('while循環:'||v_ival);
            end loop;
           
            --For循環
            for v_count in reverse 0..4 loop  --reverse遞減
                dbms_output.put_line('for循環:'||v_count);  
            end loop;
            commit;--提交事物
          end;

          select * from syslogs;

           

           

          《PL/SQL 異常處理》

          --PL/SQL異常處理:oracle內置異常,oracle用戶自定義異常
          declare
             v_title logtypes.tid%type;
             v_ival number(9,2);
             --自定義的異常
             ex_lesszero exception ;
          begin
            --select title into v_title
            --from logtypes     --;  too_many_rows
            --where tid = 30 ;  --NO_DATA_FOUND 異常
           
            v_ival := 12/-3;
           
            if v_ival < 0 then
              --直接拋出異常
              --raise ex_lesszero ;
              --使用系統存儲過程拋出異常
              raise_application_error(/*錯誤代碼,-20000~-20999*/-20003,/*異常描述*/'參數不能小于0!');
            end if; 
            commit;
          exception
            --異常處理代碼塊
            when no_data_found then
              dbms_output.put_line('發生系統異常:未找到有效的數據!');
            when too_many_rows then
              dbms_output.put_line('發生系統異常:查詢結果超出預期的一行!');
            when ex_lesszero then
              dbms_output.put_line('發生用戶異常:數值不能為負!'||sqlcode||'異常描述:'||sqlerrm);
            when others then --other例如Exception
              rollback;
              dbms_output.put_line('發生異常!'||sqlcode||'異常的描述:'||sqlerrm);
          end;

           

           

          《PL/SQL 游標的使用》


          declare
              --游標的聲明
              cursor myCur is
                     select tid,title from logtypes ;
              --定義接收游標中的數據變量
              v_tid   logtypes.tid%type;
              v_title logtypes.title%type;
              --通過記錄來接受數據
              v_typercd myCur%rowtype ;
          begin
              --打開游標
              open myCur ;
              --取游標中的數據
              loop
                --遍歷游標中的下一行數據
                fetch myCur into v_tid,v_title ;
                --檢測是否已經達到最后一行
                exit when myCur%notfound ;
                --輸出游標中的數據
                dbms_output.put_line('讀取tid='||v_tid||' title='||v_title);
              end loop;
              --關閉游標
              close myCur;
             
              --打開游標
              open myCur ;
              loop
                fetch myCur into v_typercd ;
                exit when myCur%notfound ;
                dbms_output.put_line('--//讀取tid='||v_typercd.tid||' title='||v_typercd.title);
              end loop;
              --關閉游標
              close myCur ;
             
              --for循環游標
              for tmp_record in myCur loop
                dbms_output.put_line('++//讀取tid='||tmp_record.tid||' title='||tmp_record.title);
              end loop;

          end;


           

           

          《PL/SQL 存儲過程★》


          --            可以聲明入參in,out表示出參,但是無返回值。
          create or replace procedure prc_writelog(/*日志類型*/ tid in number ,
                                        /*日志內容*/ content in varchar2 ,
                                        /*錯誤碼  */ i_ret out number ,
                                        /*錯誤描述*/ s_ret out varchar2 )
          is

          begin
                insert into syslogs values (seq_syslogs.nextval , tid ,sysdate ,content ,user);
                commit;
                i_ret := 1 ;
                s_ret := '記錄日志成功!' ;
          exception
              when others then
                   rollback ;
                   i_ret := -1 ;
                   s_ret := '記錄日志失敗:'||sqlerrm ; 
          end;

          --測試
          declare
            iRet number(4) ;
            sRet varchar2(128) ;
          begin
            prc_writelog(10,'測試存儲過程',iRet,sRet);
            dbms_output.put_line('iRet:'||iRet||'sRet'||sRet);
          end;

          select * from syslogs;

           

           

          《PL/SQL 觸發器》

           

          --觸發器 是一種基于數據庫特定事件的 由數據庫自動執行的pl/sql塊
          --觸發的事件源:database 【啟動、停止、用戶聯機...】
          --              表名【insert/update/delete】
          --觸發時機 before/after
          --語句級、行級(需要知道數據,對數據庫運行速度有影響)
          create or replace trigger tri_logtypes
          after insert or update or delete --在所有的表的事件發生后執行
          on logtypes
          for each row --行級 (:new , :old)
          declare
              iret number(4);
              sret varchar2(128);
          begin
              --不要有事物的管理
              --:new 新數據 記錄型
              --:old 原有的數據 記錄型
              --prc_writelog(10,'觸發器執行了!',iret,sret);
              if inserting then
                  insert into syslogs values(seq_syslogs.nextval,10,sysdate,'觸發器執行添加數據!',user);
              elsif updating then
                  if :new.title <> :old.title then
                     raise_application_error(-20001,'不允許修改日志類型名稱數據!');    --拋出異常
                  end if;
                  insert into syslogs values(seq_syslogs.nextval,10,sysdate,'觸發器執行更新數據!',user);
              elsif deleting then
                  raise_application_error(-20001,'不允許刪除表中的數據!');
                  insert into syslogs values(seq_syslogs.nextval,10,sysdate,'觸發器執行刪除數據!',user);
              end if;
          end ;

          --test!
          insert into logtypes values(30,'test log');
          delete from logtypes where tid = 30;
          update logtypes set title = 'test log' where tid = 30;

          select * from syslogs order by dtm desc;
          select * from logtypes ;

           

           

          《案例》

           

          --創建表
          create table emp2 (
            name varchar2(30),
            sal number(8,2)
          );
          insert into emp2 values('simple',99999);
          insert into emp2 values(&a,&b);

          --存儲過程案例:
          --修改員工工資
          create or replace procedure pro_input(t_name in varchar2,
                                     t_sal in number)
          is
          begin
            update emp2 set sal = t_sal where name=t_name;
          end;
          --Test!
          declare
          begin
            pro_input('simple',2000);
          end;
          select * from emp2;

          --函數案例:
          create or replace function fun_test(t_name varchar2)
          return number is yearSal number(7,2);
          begin
            select sal*12 into yearSal from emp2 where name = t_name;
            return yearSal;
          end;

          --包案例:
          create package pac_test
          is                           --創建一個包pac_test
            procedure pro_input(t_name varchar2,t_sal number); --聲明該包有一個過程 pro_input
            function fun_test(t_name varchar2) return number;  --聲明該包有一個函數 fun_test
          end;

          --包體案例:
          create package body pac_test
          is
            procedure pro_input(t_name in varchar2,t_sal in number)
            is
            begin
              update emp2 set sal = t_sal where name=t_name;
            end;
           
            function fun_test(t_name varchar2)
            return number is yearSal number(7,2);
            begin
              select sal*12 into yearSal from emp2 where name = t_name;
              return yearSal;
            end;
          end ;
          --調用包中的函數或過程
          call pac_test.pro_input('summer',1000);
          call pac_test.fun_test
          select pac_test.fun_test('simple') from dual;

          --案例:
          select * from emp2;
          --下面以輸入員工工號,顯示雇員姓名、工資、個人所得稅
          --稅率(0.03)。
          declare
            c_tax_rate number(3,2):=0.03;  --常量,稅率
            --v_name varchar2(30);
            v_name emp2.name%type;
            --v_sal number(8,2);
            v_sal emp2.sal%type;
            v_tax_sal number(8,2);
          begin
            --執行
            select name,sal into v_name,v_sal from emp2 where name = &na;
            --計算所得稅
            v_tax_sal:=v_sal*c_tax_rate;
            --輸出
            dbms_output.put_line('姓名:'||v_name||' 工資'||v_sal||' 交稅'||v_tax_sal); 
          end;

          --pl/sql記錄實例
          declare
            --定義一個pl/sql記錄類型 emp_record_type ,類型包含2個數據,t_name,t_sal
            type emp_record_type is record(t_name emp2.name%type,t_sal emp2.sal%type);
            --定義一個 record_test 變量,類型是 emp_record_type
            record_test emp_record_type;
          begin
            select name,sal into record_test from emp2 where name = 'simple';
            dbms_output.put_line('員工工資:'||record_test.t_sal);
          end;

          --pl/sql表實例
          declare
            --定義了一個pl/sql表類型 emp_table_type 該類型是用于存放 emp.name%type元素類型 的數組
            -- index by binary_integer 下標是整數
            type emp_table_type is table of emp2.name%type index by binary_integer;
            --定義一個 table_test 變量
            table_test emp_table_type;
          begin
            --table_test(0)下標為0的元素
            select name into table_test(0) from emp2 where name='summer';
            dbms_output.put_line('員工:'||table_test(0));
          end;


          --案例
          --顯示該部門的所有員工和工資
          declare
            --定義游標類型 emp_cursor
            type emp_cursor is ref cursor;
            --定義一個游標變量
            cursor_test emp_cursor;
            --定義變量
            v_name emp2.name%type;
            v_sal emp2.sal%type;
          begin
            --執行
            --把cursor_test 和一個select結合
            open cursor_test for
            select name,sal from emp2;
            --循環取出
            loop
              --fetch取出 游標 給 v_name,v_sal
              fetch cursor_test into v_name,v_sal;
              --判斷工資
              if v_sal<1000 then
                update emp2 set sal = v_sal+1000 where sal=v_sal;
              end if;
              --判斷cursor_test是否為空
              exit when cursor_test%notfound;
              dbms_output.put_line('姓名:'||v_name||' 薪水:'||v_sal);
            end loop;
          end;

          select * from emp2;


          --《分頁》案例:
          --建表
          drop table book;
          create table book(
            bookId number(5),
            bookName varchar2(50),
            publishHouse varchar2(50)
          );
          --編寫過程
          create or replace procedure pro_pagination( t_bookId in number,
                                      t_bookName in varchar2,
                                      t_publishHouse in varchar2)
          is
          begin
            insert into book values(t_bookId,t_bookName,t_publishHouse);
          end;
          --在java中調用
          --select * from book;
          --insert into book values(11,'流星','蝴蝶');
          --commit;
          --有輸入和輸出的存儲過程
          create or replace procedure pro_pagination2( i_id in number,
                                                       o_name out varchar2,
                                                       o_publishHouse out varchar2
                                                       )
          is
          begin
            select bookName,publishHouse into o_name,o_publishHouse from book where bookId = i_id;
          end;
          --Test!
          declare
            err book.bookname%type;
            err2 book.publishhouse%type;
          begin
            pro_pagination2(10,err,err2);
            dbms_output.put_line(err||' '||err2);
          end;
          --返回結果集的過程
          --1、創建一個包
          create or replace package testpackage
          as
            type cursor_test is ref cursor;
          end testpackage;
          --2、建立存儲過程
          create or replace procedure pro_pagination3(
                                                      o_cursor out testpackage.cursor_test)
          is
          begin
            open o_cursor for
            select * from book;
          end;
          --3、如何在java中調用

          --Test!
          declare
            err testpackage.cursor;
          begin
            pro_pagination2(10,err);
            dbms_output.put_line(err);
          end;


          <Oracle的分頁>

           

          select t1.*,rownum rn from (select * from emp) t1;

          select t1.*,rownum rn from (select * from emp) t1 where rownum<=10;
          --在分頁的時候,可以把下面的sql語句當做一個模板使用
          select * from (select t1.*,rownum rn from (select * from emp) t1 where rownum<=10) where rn>=6;

          --開發一個包
          --1、創建一個包
          create or replace package testpackage
          as
            type cursor_test is ref cursor;
          end testpackage;
          --開始編寫分頁的過程
          create or replace procedure fenye(tableName in varchar2,
                                            pageSize in number, --每頁顯示記錄數
                                            pageNow in number,
                                            myRows out number,--總記錄數
                                            myPageCount out number,--總頁數
                                            p_cursor out testpackage.cursor_test)
          is
            --定義sql語句 字符串
            v_sql varchar2(1000);
            --定義2個整數
            v_begin number:=(pageNow-1)*pageSize+1;
            v_end number:=pageNow*pageSize;
          begin
            v_sql:='select * from (select t1.*,rownum rn from (select * from '||tableName||' order by sal) t1 where rownum<='||v_end||') where rn>='||v_begin||'';
            --把游標和sql關聯
            open p_cursor for v_sql;
            --計算myRows和myPageCount
            --組織一個sql
            v_sql:='select count(*) from '||tableName||'';
            --執行sql,并把返回的值,賦給myRows
            execute immediate v_sql into myRows;
            --計算myPageCount
            if mod(myRows,pageSize)=0 then
              myPageCount:=myRows/pageSize;
            else
              myPageCount:=myRows/pageSize+1;
            end if;
            --關閉游標
            --close p_cursor;
          end;
          --使用java測試

          具體寫發 http://qindingsky.blog.163.com/blog/static/3122336200977111045401/

          posted on 2012-08-12 20:41 abin 閱讀(642) 評論(0)  編輯  收藏 所屬分類: oracle
          主站蜘蛛池模板: 于都县| 宁陕县| 屏东市| 康保县| 青阳县| 马龙县| 敦化市| 开鲁县| 平乐县| 峨边| 西丰县| 三明市| 崇左市| 弥勒县| 奇台县| 五原县| 游戏| 互助| 施甸县| 兰州市| 陇川县| 邛崃市| 新巴尔虎左旗| 鲁甸县| 济南市| 嘉义县| 泸水县| 嵊泗县| 武强县| 始兴县| 翁牛特旗| 靖边县| 集贤县| 珠海市| 法库县| 栖霞市| 德格县| 且末县| 乌拉特前旗| 宝兴县| 北碚区|