一、存儲過程和存儲函數區別:
1、本質相同,沒有區別
2、函數的存在是讓過程調用,存儲過程內部又是調用存儲函數
3、存儲函數可以在sql語句中直接調用 如 select 函數 from 表名
4、存儲過程能實現的,存儲函數也都可以實現,存儲函數可以實現的,存儲過程也都可以實現
5、存儲過程中可以沒有返回值,也可以有多個,但存儲函數中強制返回一個return
二、存儲過程和存儲函數創建
存儲過程和存儲函數創建的語法類似
create [or replace] 中 or replace是一個可選參數,表示 存在同名函數/過程 覆蓋更新,不存在則創建,一般開始創建時不推薦使用,防止將原有的刪除。
過程/函數名後面參數 參數名 in | out 參數類型 in表示輸入,out表是輸出
is ...
begin
...
end;
則和傳統的plsql編程類似,is後 定義參數變量,begin 編寫主流程語句,end表示結束。
/*
存儲過程
create [or replace] procedure 存儲過程名(參數1 in | out 參數類型,參數1 in | out 參數類型)
is
定義參數
begin
過程...
end;
*/
/*
存儲函數
create [or replace] function 函數名(參數1 in 參數類型,參數1 in 參數類型) return 返回值類型
is | as
定義參數
begin
存儲函數過程
end;
*/
三、存儲過程和存儲函數的事例
eg 例子:
-- 根據empno求emp年薪 存儲函數
create or replace function fun_getsumsal(vempno in number) return number
is
vsumsal number;
begin
select sal*12 + nvl(comm,0) into vsumsal from emp where empno = vempno;
return vsumsal;
end;
-- plsql編程調用
declare
begin
dbms_output.put_line(fun_getsumsal(7369));
end;
-- 存儲過程實現年薪
create procedure proc_gettotalsal(vempno in number,totalsal out number)
is
begin
select sal*12 + nvl(comm,0) into totalsal from emp where empno = vempno;
end;
-- plsql編程調用
declare
total number;
begin
proc_gettotalsal(7369,total);
dbms_output.put_line(total);
end;
四、java代碼調用存儲過程和存儲函數
java調用方法類似,都是先jdbc連接數據庫,通過conn.prepareCall(sql)的這個方法進行存儲過程和存儲函數的調用。
不同的sql書寫方式
存儲過程:String sql = "{call proc_gettotalsal(?,?)}"; {call 存儲過程名(?,?)} 無返回值
存儲函數:String sql = "{ ? = call proc_gettotalsal(?)}"; {? = call 存儲過程名(?)} 有返回值
? 是後續conn.prepareCall(sql);獲取的CallableStatement:statement進行參數設置,輸入可以直接使用set方法,輸出使用statement.registerOutParameter(int num, OracleTypes.NUMBER)方法,第一個參數代碼代碼?的索引,也就是第幾個,第二個參數代碼輸出值得類型。
(1)調用存儲過程
@Test
public void demo1() throws Exception {
//註冊驅動
Class.forName("oracle.jdbc.driver.OracleDriver");
//獲取連接
String url = "jdbc:oracle:thin:@127.0.0.1:1521:orcl";
String username = "jzxy";
String password = "jzxy";
Connection conn = DriverManager.getConnection(url, username, password);
//獲取執行SQL的statement.這是一個固定格式 proc_gettotalsal是一個存儲函數
String sql = "{call proc_gettotalsal(?,?)}";
CallableStatement statement = conn.prepareCall(sql);
// 設置輸入參數
statement.setInt(1, 7369);
// 設置輸出參數
statement.registerOutParameter(2, OracleTypes.NUMBER);
// 執行
statement.execute();
// 獲取輸出值
int total = statement.getInt(2);
System.out.println(total);
// 關閉資源
statement.close();
conn.close();
}
(2)調用存儲函數
@Test
public void demo2() throws Exception {
//註冊驅動
Class.forName("oracle.jdbc.driver.OracleDriver");
//獲取連接
String url = "jdbc:oracle:thin:@127.0.0.1:1521:orcl";
String username = "jzxy";
String password = "jzxy";
Connection conn = DriverManager.getConnection(url, username, password);
//獲取執行SQL的statement.這是一個固定格式 proc_gettotalsal是一個存儲函數
String sql = "{? = call fun_getsumsal(?)}";
CallableStatement statement = conn.prepareCall(sql);
// 設置輸出參數
statement.registerOutParameter(1, OracleTypes.NUMBER);
// 設置輸入參數
statement.setInt(2, 7369);
// 執行
statement.execute();
// 獲取輸出值
int total = statement.getInt(1);
System.out.println(total);
// 關閉資源
statement.close();
conn.close();
}