存儲過程和存儲函數 指存儲在資料庫中供所有用戶程式調用的子程式叫存儲過程、存儲函數。 存儲過程和存儲函數的區別? 存儲函數:可以通過return 語句返回函數值。 存儲過程:不能 除此之外我們可以認為他們是完全一樣的。 存儲過程 1、創建存儲過程 用create procedure命令簡歷存儲過程。 ...
存儲過程和存儲函數 指存儲在資料庫中供所有用戶程式調用的子程式叫存儲過程、存儲函數。 存儲過程和存儲函數的區別? 存儲函數:可以通過return 語句返回函數值。 存儲過程:不能 除此之外我們可以認為他們是完全一樣的。 存儲過程 1、創建存儲過程 用create procedure命令簡歷存儲過程。 語法: create [or replace] procedure 過程名(參數列表) as PLSQL子程式體; 列印hello word
--列印hello world create or replace procedure sayhelloworld as --說明部分 begin dbms_output.put_line('hello world'); end; /
編譯後:
2、調用存儲過程方法: 1、exec 過程名 2、begin 過程名; 過程名; end; / 測試調用存儲過程--連接資料庫 C:\WINDOWS\system32>sqlplus scott/tiger@192.168.56.101:1521/orcl SQL>--調用方式一 SQL> set serveroutput on SQL> exec sayhelloworld; hello world PL/SQL 過程已成功完成。 SQL> --調用方式二: SQL> begin 2 sayhelloworld(); 3 sayhelloworld(); 4 end; 5 / hello world hello world PL/SQL 過程已成功完成。
帶參數的存儲過程:
--給指定員工薪水漲100,並且列印漲前和漲後的薪水 create or replace procedure raiseSalary(eno in number) --in為輸入參數 as --說明部分 psal emp.sal%type; begin --得到漲前的薪水 select sal into psal from emp where empno=eno; update emp set sal=sal+100 where empno=eno; --要不要commit? --為保證在同一事務中,commit由誰調用誰提交 dbms_output.put_line('漲前:'||psal||' 漲後:'||(psal+100)); end; /
測試:
存儲函數 函數(function)為一命名的存儲程式,可帶參數,並返回一計算值。函數和過程的結構類似,但必須有一個return子句,用於返回函數值。函數說明要指定函數名、結果值的類型,以及參數類型等。 存儲函數語法: create[or replace] functiion 函數名(參數列表) return函數值類型 as PLSQL子程式體; 查詢員工年收入--查詢某個員工的年收入 create or replace function queryempincome(eno in number) return number as --月薪和獎金 psal emp.sal%type; pcomm emp.comm%type; begin select sal,comm into psal,pcomm from emp where empno=eno; --返回年收入 return psal*12+nvl(pcomm,0); end; /
測試:
過程和函數中的in 和out 一般來講,過程和函數的區別在於函數可以有一個返回值;而過程沒有返回值。 但過程和函數都可以通過out指定一個或多個輸出參數,我們可以利用out參數,在過程和函數中實現返回多個值。 什麼時候用存儲過程/存儲函數? 原則(不是必須的): 如果只有一個返回值,用存儲函數;否則,就用存儲過程。 存儲過程create or replace procedure queryEmpInfo(eno in number, pname out varchar2, psal out number, pjob out varchar2) as begin select ename,sal,empjob into pname,psal,pjob from emp where empno=eno; end;
測試
使用java程式調用存儲過程
/* * 存儲過程 * create or replace procedure queryEmpInfo(eno in number, * pename out varchar2, * psal out number, * pjob out varchar2) */ @Test public void testProcedure() { // {call <procedure-name>[(<arg1>,<arg2>, ...)]} String sql = "{call queryEmpInfo(?,?,?,?)}"; CallableStatement call = null; Connection connection = JDBCUtils.getConnection(); try { call = connection.prepareCall(sql); //對於in參數,賦值 call.setInt(1, 7839); //對於out參數,聲明 call.registerOutParameter(2, OracleTypes.VARCHAR); call.registerOutParameter(3, OracleTypes.NUMBER); call.registerOutParameter(4, OracleTypes.VARCHAR); //執行 call.execute(); //取出結果 String name = call.getString(2); double sal = call.getDouble(3); String job = call.getString(4); System.out.println(name + "\t" + sal + "\t" + job); } catch (SQLException e) { e.printStackTrace(); }finally{ JDBCUtils.release(connection, call, null); } }
使用java程式調用存儲函數
/* * 存儲函數 * create or replace function queryEmpIncome(eno in number) return number */ @Test public void testFunction() { // {?= call <procedure-name>[(<arg1>,<arg2>, ...)]} String sql = "{?=call queryEmpIncome(?)}"; Connection conn = null; CallableStatement call = null; try { conn = JDBCUtils.getConnection(); call = conn.prepareCall(sql); //對於out參數,賦值 call.registerOutParameter(1, OracleTypes.NUMBER); //對於in參數,賦值 call.setInt(2, 7839); //執行 call.execute(); //取出數據 double income = call.getDouble(1); System.out.println(income); } catch (Exception e) { e.printStackTrace(); } finally { JDBCUtils.release(conn, call, null); } }在out參數中使用游標 問題:查詢某個部門中所有員工的所有信息 1、申明包結構
CREATE OR REPLACE PACKAGE MYPACKAGE AS type empcursor is ref cursor; --創建存儲過程,輸出參數為自定義類型 procedure queryEmpList(dno in number,empList out empcursor); END MYPACKAGE;
2、創建包體(實現)
CREATE OR REPLACE PACKAGE BODY MYPACKAGE AS procedure queryEmpList(dno in number,empList out empcursor) AS BEGIN --實現 open empList for select * from emp where deptno=dno; END queryEmpList; END MYPACKAGE;使用java調用帶包的存儲過程
public void testCursor() { // {call <procedure-name>[(<arg1>,<arg2>, ...)]} String sql = "{call MYPACKAGE.queryEmpList(?,?)}"; Connection conn = null; CallableStatement call = null; ResultSet rs = null; try { conn = JDBCUtils.getConnection(); call = conn.prepareCall(sql); //對於in參數,賦值ֵ call.setInt(1, 20); //對於out參數,賦值 call.registerOutParameter(2, OracleTypes.CURSOR); //執行 call.execute(); // 取出結果 rs = ((OracleCallableStatement)call).getCursor(2); while(rs.next()){ String name = rs.getString("ename"); double sal = rs.getDouble("sal"); System.out.println(name+"\t"+sal); } } catch (Exception e) { e.printStackTrace(); } finally { JDBCUtils.release(conn, call, rs); } }
此案例游標沒有關閉,原因:當resultSet關閉的時候 游標就close了