一、存儲過程
1、定義
所謂存儲過程(Stored Procedure),就是一組用於完成特定數據庫功能的SQL語句集,該SQL語句集經過編譯後存儲在數據庫系統中。在使用時候,用戶通過指定已經定義的存儲過程名字並給出相應的存儲過程參數來調用並執行它,從而完成一個或一系列的數據庫操作。
2、存儲過程的創建
Oracle存儲過程包含三部分:過程聲明,執行過程部分,存儲過程異常。
(一)無參存儲過程語法
create or replace procedure NoParPro
as //聲明
;
begin // 執行
;
exception//存儲過程異常
;
end;
(二)帶參存儲過程實例
create or replace procedure queryempname(sfindno emp.empno%type)
as
sName emp.ename%type;
sjob emp.job%type;
begin
....
exception
....
end;
(三)帶參數存儲過程含賦值方式
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表示該參數可以向該過程中傳遞值,也可以將某個值傳遞出去。
(四)存儲過程中游標定義使用
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;
(五)遊標定義
--顯示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中對存儲過程的調用
(一)過程調用方式一
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; //過程調用結束
(二)過程調用方式二
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; //過程調用結束
(三)過程調用方式三(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存儲過程
(一)不帶輸出參數情況,過程名稱爲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();
}
}
(二)帶輸出參數的情況,過程名稱爲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');