1. 程式人生 > >【PL/SQL】儲存過程詳解

【PL/SQL】儲存過程詳解

什麼是儲存過程

儲存過程是一種命名的PL/SQL程式塊,既可以沒有引數也可以有若干個輸入,輸出引數,但是它通常沒有返回值。儲存過程被儲存在資料庫中,可以被SQL語句直接呼叫,只能通過EXECUT命令或者在PL/SQL程式塊內部被呼叫。由於儲存過程是已經編譯好的程式碼,因此被呼叫或者引用時,執行效率非常高。

建立儲存過程

示例如下:

create or replace procedure pro_name (parameter1,parameter2) is
begin 
    plsql_sentences;
[exception]
    [dowith_sentences;]
end [pro_name];

注意一下,is和as的區別:在Oracle的儲存過程和函式中,其實IS和AS是同義詞,沒有什麼區別。還有在自定義型別(TPYE)和包(PACKAGE)時,使用IS和AS也並沒有什麼區別。但是在建立檢視(VIEW)時,只能使用AS而不能使用IS。在宣告遊標(CURSOR)時,只能使用IS而不能使用AS。

pro_name:儲存過程名字,parameter1儲存過程的引數;plsql_sentences:PL/SQL語句,它是儲存過程實現的主體。dowith_sentences:異常處理語句。中括號[]是可有可無的

建立一個插入的儲存過程示例:

SQL> create or replace procedure pro_insertDept is 
    begin 
          insert into dept values(77,'市場拓展部','JJ');
          commit;
          dbms_output.put_line('插入的新記錄成功!');
    end pro_insertDept;
/

注意:在PL/SQL的命令窗口裡面必須用“/”強制退出

呼叫儲存過程的示例如下:

SQL> execute pro_insertDetp;     --執行的儲存過程

或者如下:

SQL> set serverout on;  --這個只能在SQL PLUS裡面使用,意思是在窗口裡顯示伺服器輸出資訊
SQL> begin 
        pro_insertDept;
    end;
/                 --強制退出命令

注意:set serverout on;  --這個只能在SQL PLUS裡面使用,意思是在窗口裡顯示伺服器輸出資訊

儲存過程的引數

IN模式引數:這是一種輸入型別的引數,引數值有呼叫方傳入,並且只能被儲存過程讀取。這種模式是最常用的,關鍵字in位於引數名稱之後。

SQL> create or replace procedure insert_dept(
    num_deptno in number,  
    var_ename in varchar2,
    var_loc in varchar2
)  is 
    begin 
    isnert into dept values (num_deptno,var_ename,var_loc);
    commit;
    end insert_dept;
/

注意一下:引數型別的不能指定長度。

  • 指定名稱傳遞:指在向儲存過程傳遞引數的時需要指定引數名稱(與順序無關,但名字要一致),即引數名稱在左側,中間是賦值符號“=>”,右側是引數值
SQL>begin 
    insert_dept(var_ename=>'採購部',var_loc=>'成都',num_deptno=>15);
    end;
/

 

  • 按位置傳遞:提供的引數數值順序必須與儲存過程中定義的引數順序相同
SQL>begin 
    insert_dept(28,'工程部','洛陽');
    end ;
    /
  • 混合方式傳遞: 混合方式及時將兩種結合到一起,兼顧兩者的有點 

混合方法需要注意:上面兩種呼叫方式可混合使用,但是注意,一旦某個引數有使用命名符,則後面所有的引數都得使用命名符,  否則會導致異常:“PLS-00312:一個定位相關引數沒有說明其相關性

in 引數的預設值:是在宣告時初始化預設值,用default關鍵字

SQL>create or replace procedure insert_dept(
    num_deptno in numnber,
    var_dname in varchar2 default '綜合部',
    var_loc in varchar2 default '北京'
) is 
    begin 
        insert into dept values(num_deptno,var_dname,var_loc);
    end;
/

 

 out模式引數:輸出型別引數,關鍵字out位於引數名稱之後

建立示例:

SQL> create or replace procedure select_dept(
    num_deptno in number,
    var_dname out dept.dname%type,
    var_loc out dept.loc%type
) is begin 
    select dname,loc into var_dname,var_loc from dept 
    where deptno = num_deptno;
end select_dept;
/

注意一下:SELECT INTO 語句從一個表複製資料,然後把資料插入到另一個新表中。

(1)在PL/SQL塊中呼叫out模式的儲存過程,需要在PL/SQL塊declare部分定義與儲存過程中out引數型別相容的若干變數

SQL>set serverout on
SQL> declare 
    var_dname dept.dname%type;
    var_loc dept.loc%type;
    begin 
    select _dept(99,var_dname,var_loc);
    dbms_output.putline(var_dname||'位於:'||var_loc);
end;
/

注意:select_dept(num_deptno=>99,var_dname,var_loc),這樣寫會報錯:一個定位相關引數沒有說明其相關性,必須這樣寫:select_dept(num_deptno=>99,var_dname=>var_dname,var_loc=>var_loc);=>左邊的是引數名,要和儲存過程內部一致,右側是引數值。

(2)用exec命令執行out模式的儲存過程,在SQL*Plus環境中使用variable關鍵字宣告兩個變數,用以儲存out引數的返回值

例如:

SQL>variable var_dname varchar2(50);
SQL>variable var_loc varchar2(50);
SQL>exec select_dept(15,:var_dname,:var_loc);

但是使用者看不到var_dname和var_loc的值,可以通過print或者select檢視

 SQL>print var_dname var_loc;

 select :var_dname,:var_loc from dual;

  • 使用print命令檢視
  • 使用select語句檢索繫結的變數值

IN OUT 模式引數:在執行儲存過程中,in引數不能被修改,只能根據被傳入的指定值為儲存過程提供資料,而out型別只能等待被賦值,IN out 引數可以兼顧兩者的優點,在呼叫的時候,從外界向該型別的引數傳入值,執行完之後,將結果返回值傳給外界

in out 引數示例:

SQL>create or replace procedure pro_square(
    num in out number,
    flag in boolen 
) is i int :=2;
begin 
    if flag then 
            num :=power(num,i);
       else
            num :=sqrt(num);
    end if;
end;
/

呼叫如下:

SQL>declare var_number number;
            var_temp number;
            boo_flag boolean;
begin 
   var_temp :=3;
    var_number :=var_temp;
    boo_flag :=false;
    pro_square(var_number,boo_flag);
    if boo_flag then 
        dbms_output.put_line(var_temp||'的平方是:'var_number);
    else
        dbms_output.put_line(var_temp||'的平方根是:'var_number);
    end if;
end;
/