【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;
/