一、 存儲過程
1、定義
所謂存儲過程(Stored Procedure),就是一組用於完成特定數據庫功能的SQL語句集,該SQL語句集經過
編譯後存儲在數據庫系統中。在使用時候,用戶通過指定已經定義的存儲過程名字並給出相應的存儲過程參數
來調用並執行它,從而完成一個或一系列的數據庫操作。
2、存儲過程的創建
Oracle存儲過程包含三部分:過程聲明,執行過程部分,存儲過程異常。
(1)無參存儲過程語法
-
create or replace procedure NoParPro -
as //聲明 -
; -
begin // 執行 -
; -
exception//存儲過程異常 -
; -
end;
(2)帶參存儲過程實例
- create or replace procedure queryempname(sfindno emp.empno%type)
- as
- sName emp.ename%type;
- sjob emp.job%type;
- begin
- ….
- exception
- ….
- end;
(3)帶參數存儲過程含賦值方式
- create or replace procedure runbyparmeters
- (isal in emp.sal%type,
- sname out varchar,
- sjob in out varchar)
- as
- icount number;
- begin
- select count(*) into icount from emp where sal>isal and job=sjob;
- if icount=1 then
- ….
- else
- ….
- end if;
- exception
- when too_many_rows then
- DBMS_OUTPUT.PUT_LINE(’返回值多於1行’);
- when others then
- DBMS_OUTPUT.PUT_LINE(’在RUNBYPARMETERS過程中出錯!’);
- end;
其中參數IN表示輸入參數,是參數的默認模式。
OUT表示返回值參數,類型可以使用任意Oracle中的合法類型。
OUT模式定義的參數只能在過程體內部賦值,表示該參數可以將某個值傳遞迴調用他的過程
IN OUT表示該參數可以向該過程中傳遞值,也可以將某個值傳出去。
(4)存儲過程中游標定義使用
- as //定義(遊標一個可以遍歷的結果集)
- CURSOR cur_1 IS
- SELECT area_code,CMCODE,SUM(rmb_amt)/10000 rmb_amt_sn,
- SUM(usd_amt)/10000 usd_amt_sn
- FROM BGD_AREA_CM_M_BASE_T
- WHERE ym >= vs_ym_sn_beg
- AND ym <= vs_ym_sn_end
- GROUP BY area_code,CMCODE;
- begin //執行(常用For語句遍歷遊標)
- FOR rec IN cur_1 LOOP
- UPDATE xxxxxxxxxxx_T
- SET rmb_amt_sn = rec.rmb_amt_sn,usd_amt_sn = rec.usd_amt_sn
- WHERE area_code = rec.area_code
- AND CMCODE = rec.CMCODE
- AND ym = is_ym;
- END LOOP;
(5)遊標的定義
- –顯示cursor的處理
- declare
- —聲明cursor,創建和命名一個sql工作區
- cursor cursor_name is
- select real_name from account_hcz;
- v_realname varchar2(20);
- begin
- open cursor_name;—打開cursor,執行sql語句產生的結果集
- fetch cursor_name into v_realname;–提取cursor,提取結果集中的記錄
- dbms_output.put_line(v_realname);
- close cursor_name;–關閉cursor
- end;
3、在Oracle中對存儲過程的調用
(1)過程調用方式一
-
declare -
realsal emp.sal%type; -
realname varchar(40); -
realjob varchar(40); -
begin //過程調用開始 -
realsal:=1100; -
realname:=”; -
realjob:=’CLERK’; -
runbyparmeters(realsal,realname,realjob);--必須按順序 -
DBMS_OUTPUT.PUT_LINE(REALNAME||’ ’||REALJOB); -
END; //過程調用結束
(2)過程調用方式二
-
declare -
realsal emp.sal%type; -
realname varchar(40); -
realjob varchar(40); -
begin //過程調用開始 -
realsal:=1100; -
realname:=”; -
realjob:=’CLERK’; -
--指定值對應變量順序可變 -
runbyparmeters(sname=>realname,isal=>realsal,sjob=>realjob); -
DBMS_OUTPUT.PUT_LINE(REALNAME||’ ’||REALJOB); -
END; //過程調用結束
(3)過程調用方式三(SQL命令行方式下)
-
1、SQL>exec proc_emp(‘參數1’,‘參數2’);//無返回值過程調用 -
2、SQL>var vsal number -
SQL> exec proc_emp (‘參數1’,:vsal);// 有返回值過程調用 -
或者:call proc_emp (’參數1’,:vsal);// 有返回值過程調用
4、JAVA調用Oracle存儲過程
(1)不帶輸出參數情況,過程名稱爲pro1,參數個數1個,數據類型爲整形數據
-
import java.sql. * ; -
public class ProcedureNoArgs{ -
public static void main(String args[]) throws Exception{ -
//加載Oracle驅動 -
DriverManager.registerDriver( new oracle.jdbc.driver.OracleDriver()); -
//獲得Oracle數據庫連接 -
Connection conn = DriverManager.getConnection -
(”jdbc:oracle:thin:@MyDbComputerNameOrIP:1521:ORCL”, sUsr, sPwd ” ); -
//創建存儲過程的對象 -
CallableStatement c = conn.divpareCall( ” {call pro1(?)} ” ); -
//給Oracle存儲過程的參數設置值 ,將第一個參數的值設置成188 -
c.setInt( 1 , 188 ); -
// 執行Oracle存儲過程 -
c.execute(); -
conn.close(); -
} -
}
(2)帶輸出參數的情況,過程名稱爲pro2,參數個數2個,數據類型爲整形數據,返回值爲整形類型。
-
import java.sql.*; -
public class ProcedureWithArgs { -
public static void main(String args[]) throws Exception{ -
//加載Oracle驅動 -
DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver()); -
//獲得Oracle數據庫連接 -
Connection conn = DriverManager.getConnection -
(”jdbc:oracle:thin:@MyDbComputerNameOrIP:1521:ORCL”, sUsr, sPwd ”); -
//創建Oracle存儲過程的對象,調用存儲過程 -
CallableStatement c=conn.divpareCall(”{call pro2(?,?)}”); -
//給Oracle存儲過程的參數設置值 ,將第一個參數的值設置成188 -
c.setInt(1,188); -
//註冊存儲過程的第二個參數 -
c.registerOutParameter(2,java.sql.Types.INTEGER); -
c.execute(); //執行Oracle存儲過程 -
//得到存儲過程的輸出參數值並打印出來 -
System.out.println (c.getInt(2)); -
conn.close(); -
} -
}
二、 函數
1、基本語法規則
-
create or replace function (Name in type, Name in type, …) -
return number -
is -
Result number; -
begin -
return (Result); -
end ;
2、具體事例(查詢出empno=7935的sal值)
-
create or replace function ret_emp_sal(v_ename varchar2) -
return number -
is -
v_sal number(7,2); -
begin -
select nvl(sal,0) into v_sal from emp where lower(ename)=lower(v_ename); -
return v_sal; -
end;
3、函數調用:
-
SQL> var vsla number -
SQL> call ret_emp_sal(’7935’) into :vsal;
4、與存儲過程的區別
(1)返回值的區別,函數有1個返回值,而存儲過程是通過參數返回的,可以有多個或者沒有
(2)調用的區別,函數可以在查詢語句中直接調用,而存儲過程必須單獨調用.
(3)使用場景的區別,函數一般情況下是用來計算並返回一個計算結果
而存儲過程一般是用來完成特定的數據操作(比如修改、插入數據庫表或執行某些DDL語句等等)
三、包
包用於組合邏輯相關的過程和函數,它由包規範和包體兩個部分組成。包規範用於定義公用的常量、變量、過程
和函數,創建包規範可以使用CREATE PACKAGE命令,創建包體可以使用CREATE PACKAGE BODY.
1、創建包規範
-
create package emp_pkg is -
procedure emp_update_ename(v_empno varchar2,v_ename varchar2); -
function emp_get_sal(v_empno varchar2) return number; -
end;
2、創建包體
-
create or replace package body emp_pkg -
is -
// 存儲過程 -
procedure emp_update_ename -
( -
v_empno varchar2, -
v_ename varchar2 -
) -
is -
vename varchar2(32); -
begin -
update emp set ename=v_ename where empno=v_empno; -
commit; -
select ename into vename from emp where empno=v_empno; -
dbms_output.put_line(’僱員名稱:’||vename); -
end; -
// 函數 -
function emp_get_sal -
( -
v_empno varchar2 -
) -
return number is -
vsal number(7,2); -
begin -
select sal into vsal from emp where empno=v_empno; -
return vsal; -
end; -
nd;
3、包調用
在沒有創建包規範就創建包體,會失敗,要使用包,必須先創建包規範,然後在創建包體。
當要調用包的過程和函數時,在過程和函數的名稱前加上包名作爲前綴(包名.子程序名稱),
而如果要訪問其他方案的包時需要在包的名稱前加上方案的名稱(方案名稱.包名.子程序名稱)。
(1)調用包函數
-
SQL> var vsla number -
SQL> call emp_pkg.emp_get_sal(’7935’) into :vsal;
(2)調用包存儲過程
-
SQL> exec emp_pkg.emp_update_ename(‘7935’,‘helong’);