日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

oracle as 不可以省略,Oracle:存储过程,存储函数

發(fā)布時間:2025/3/19 编程问答 41 豆豆
生活随笔 收集整理的這篇文章主要介紹了 oracle as 不可以省略,Oracle:存储过程,存储函数 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

什么是存儲過程和存儲函數(shù):指存儲在數(shù)據(jù)庫中供所有用戶程序調(diào)用的子程序叫做存儲過程、存儲函數(shù)。

這個子程序是用PL/SQL寫的??梢杂肑ava程序調(diào)用,就是完成特定功能的子程序。

用create procedure命令創(chuàng)建存儲過程。

語法:

Create [or replace] procedure 過程名(參數(shù)列表) asPLSQL子程序體;

As相當(dāng)于declare,所以我們可以在as后面定義變量。As不可以省略。

--打印Hello World。

Create or replace procedure sayHelloWorld

As

--說明部分

Begin

Dbms_output.put_line(‘HelloWorld’);

End;

/

先將存儲過程編譯,在SQL Developer左邊的樹結(jié)構(gòu)中的過程里就產(chǎn)生了這個存儲過程。

如果圖標上有小紅叉,表示有語法錯誤,如果是綠葉,表示沒有問題。這個存儲過程的功能是打印HelloWorld。

如何調(diào)用這個存儲過程呢?

第一種方式:使用execute命令

Exec sayHelloWorld();

第二種調(diào)用方式:

Begin

sayHelloWorld();

sayHelloWorld();

sayHelloWorld();

end;

/

帶參數(shù)的存儲過程:

--給指定員工的工資漲100元工資,并且打印漲前和漲后的薪水。

--既然是指定,就是員工會變化,所以要接收一個員工參數(shù)。

--指定參數(shù)的時候要分為輸入?yún)?shù)和輸出參數(shù),默認是輸入?yún)?shù),但是顯示指出比較好,用in指出。

Create or replace procedure raiseSalary(enoin number)

As

--變量

Psalemp.sal%type;

Begin

--得到漲前的薪水。

Selectsal into psal from emp where empno = eno;

--漲100元

Updateemp set sal = sal + 100 where empno = eno;

--這里不要提交事務(wù),誰調(diào)用誰來提交事務(wù)

--打印漲前和漲后的薪水。

Dbms_output.put_line(‘漲前:’||psal||’漲后’||(psal+100));

End;

/

編譯。

調(diào)用:

Begin

raiseSalary(7839);

raiseSalary(7566);

commit;

end;

/

存儲過程和存儲函數(shù)的區(qū)別:

存儲過程沒有返回值,存儲函數(shù)可以有一個返回值。

存儲函數(shù):

函數(shù)為一命名的存儲程序,可以帶參數(shù),并返回一個計算值。函數(shù)和過程的結(jié)構(gòu)類似,但必須有一個return子句,用于返回函數(shù)值。函數(shù)說明要指定函數(shù)名、結(jié)果值的類型,以及參數(shù)類型等。

語法:

Create [or replace] function 函數(shù)名(參數(shù)列表)

Return 函數(shù)值類型

As

PLSQL子程序體;

--查詢某個員工的年收入,通過函數(shù)查詢,查詢完將查詢結(jié)果返回。

--接收一個員工參數(shù)

Create or replace functionqueryEmpIncome(eno in number)

Return number

As

--年收入與月薪和獎金有關(guān),定義兩個變量,接收月薪和獎金。

Psalemp.sal%type;

Pcommemp.comm%type;

Begin

--得到該員工的月薪和獎金

Selectsal,comm into psal,pcomm from emp where empno = eno;

--返回年收入

Returnpsal*12+nvl(pcomm,0);

End;

/

編譯一下,在左邊的樹結(jié)構(gòu)中就出現(xiàn)了函數(shù)的部分。

直接在圖標上點右鍵選擇運行就可以運行。

打開對話框,傳參數(shù):

控制臺結(jié)果:

雙擊函數(shù),可以打開一個窗口,這個窗口有debug的功能,在側(cè)邊雙擊可以打斷點。

Debug需要權(quán)限,需要授權(quán)。

Grant DEBUG CONNECT SESSION , DEBUG ANY PROCEDUREto scott;

關(guān)于輸出參數(shù):

存儲過程和存儲函數(shù)都可以通過out指定一個或多個輸出參數(shù)。我們可以利用out參數(shù),在過程和函數(shù)中實現(xiàn)返回多個值。

原則:如果只有一個返回值,用存儲函數(shù),否則,就用存儲過程。

--out參數(shù)的例子。查詢并返回某個員工的姓名 月薪 職位

--因為要返回姓名,月薪,職位,就要在參數(shù)中定義為輸出參數(shù)。

Create or replace procedurequeryEmpInfo(eno in number,pename out varchar2,psal out number,pjob outvarchar2)

As

Begin

Selectename,sal,empjob into pename,psal,pjob from emp where empno = eno;

End;

/

編譯,在過程上刷新,右鍵運行。

如何在Java程序中調(diào)用存儲過程或存儲函數(shù)呢?

先獲取Connection,在獲取CallableStatement(Statement的子類)。

通過Connection的prepareCall(String sql)方法創(chuàng)建CallableStatement。

CallableStatement是用來執(zhí)行SQL存儲過程的接口。JDBCAPI提供了一個存儲過程SQL轉(zhuǎn)義語法,該語法允許對所有RDBMS使用標準方式調(diào)用存儲過程。

調(diào)用的SQL語法:

調(diào)存儲函數(shù):?=call[(,,…)]

掉存儲過程:call[(,…)]

調(diào)用示例:用PL/SQL比直接使用SQL調(diào)用效率要高。

創(chuàng)建工程,導(dǎo)入Oracle的jar包。Jar包位置如地址欄所示。

(1)JDBC工具類

Public class JDBCUtils {

Private static String driver = “oracle.jdbc.OracleDriver”;

Private static String url = “jdbc:oracle:thin:@localhost:1521:orcl”;

Private static String user = “scott”;

Private static String password = “tiger”;

Static {

Try{

Class.forName(driver);

} catch (ClassNotFoundException e) {

e.printStackTrace();

}

}

Public static Connection getConnection() {

Try{

Return DriverManager.getConnection(url,user,password);

} catch (SQLException e) {

e.printStackTrace();

}

Return null;

}

Public static void release(Connection conn,Statement st, ResultSet rs) {

If(rs != null) {

Try{

Rs.close();

} catch(SQLException e) {

e.printStackTrace();

} finally {

Rs = null; //為是么置null呢?需要垃圾回收,gc機制。

}

}

If(st != null) {

Try{

st.close();

} catch(SQLException e) {

e.printStackTrace();

} finally {

st = null;

}

}

If(conn != null) {

Try{

conn.close();

} catch(SQLException e) {

e.printStackTrace();

} finally {

conn = null;

}

}

}

}

Public class TestOracle {

@Test

Public void testProcedure() {

//第一個是輸入?yún)?shù),后三個是輸出參數(shù)。

String sql = “{call queryEmpInfo(?,?,?,?)}”;

Connection conn = null;

CallableStatement call = null;

Try {

Conn = JDBCUtils.getConnection();

Call = conn.prepareCall(sal);

//對于in參數(shù)賦值

Call.setInt(1,7839);

//對于out參數(shù)。在執(zhí)行后才有值。通過OracleTypes中的常量可以將Oracle的類型轉(zhuǎn)換成Java的類型

Call.registerOutParameter(2,OracleTypes.VARCHAR);

Call.registerOutParameter(3,OracleTypes.NUMBER);

Call.registerOutParameter(4,OracleTypes.VARCHAR);

//執(zhí)行

Call.execute();

//取出結(jié)果。

String name = call.getString(2);

double sal = call.getDouble(3);

String job = call.getString(4);

System.out.println(name);

System.out.println(sal);

System.out.println(job);

}catch(Exception e){

e.printStackTrace();

}finally{

JDBCUtils.release(conn,call,null);

}

}

@Test

Public void testFunction(){

String sql = “{?=call queryEmpIncone(?)}”;

Connection conn = null;

CallableStatement call = null;

Try {

Conn = JDBCUtils.getConnection();

Call = conn.prepareCall(sal);

//第一個參數(shù)是返回值,先處理out參數(shù)

//對于out參數(shù)。在執(zhí)行后才有值。通過OracleTypes中的常量可以將Oracle的類型轉(zhuǎn)換成Java的類型

Call.registerOutParameter(1,OracleTypes.NUMBER);

//對于in參數(shù)賦值

Call.setInt(2,7839);

//執(zhí)行

Call.execute();

//取出結(jié)果。

double income = call.getDouble(1);

System.out.println(income);

}catch(Exception e){

e.printStackTrace();

}finally{

JDBCUtils.release(conn,call,null);

}

}

}

--返回某個部門的所有員工的所有信息。這樣out就太多了

--可以通過在光標中定義。

在out中使用光標,有一個要求,必須將光標和存儲過程或者存儲函數(shù)放到一個包里面。

什么是包?

是一個數(shù)據(jù)庫對象,是包頭,包頭只負責(zé)聲明,包體只負責(zé)實現(xiàn)。

聲明包:

--例:根據(jù)員工的員工號查詢員工信息,要求返回員工的所有信息。

Create or replace package MYPACKAGE as

--自定義一個類型empcursor,這個類型引用cursor光標類型,也就是說,設(shè)個empcursor類型就是一個光標

Type empcursoris ref cursor;

--在out中使用自定義的光標類型

Procedurequeryemp(eid in number,empinfo out empcursor);

End MYPACKAGE;

什么是包體?

也是一個數(shù)據(jù)庫對象,包體要實現(xiàn)存儲過程和存儲函數(shù)。

CREATE OR REPLACE

PACKAGE BODY MYPACKAGE AS

PROCEDUREqueryemp(eid in number,empinfo out empcursor) AS

BEGIN

Openempinfo for select * fro emp where empno = eid;

ENDqueryemp;

END MYPACKAGE;

--返回某個部門的所有員工的所有信息

CREATE OR REPLACE

PACKAGE MYPACKAGE AS

Typeempcursor is ref cursor;

ProcedurequeryEmpList(dno in number,empList out empcursor);

END MYPACKAGE;

--編譯好后,在左邊的樹結(jié)構(gòu)中的程序包節(jié)點中就有了剛定義的包。右鍵,可以選擇創(chuàng)建包體。

--會將包頭中所有需要實現(xiàn)的程序都列出來。

CREATE OR REPLACE

PACKAGE BODY MYPACKAGE AS

ProcedurequeryEmpList(dno in number,empList out empcursor) AS

BEGIN

--這里open了光標,并沒有關(guān)閉光標,其實光標關(guān)閉了,

--因為在返回rs結(jié)果集后,程序關(guān)閉了rs,關(guān)閉了rs也就關(guān)閉了光標。

OpenempList for select * from emp where deptno = dno;

ENDqueryEmpList;

END MYPACKAGE;

//編寫測試程序

@Test

Public void testCursor() {

String sql = “{call MYPACKAGE.queryEmpList(?,?)}”;

Connection conn = null;

CallableStatement call = null;

ResultSet rs = null;

Try{

Conn = JDBCUtils.getConnection();

Call = conn.prepareCall(sql);

//對于in參數(shù)賦值。部門號

Call.setInt(1,10);

//對于out參數(shù),所有員工的所有信息。

Call.registerOutParameter(2,OracleTypes.CURSOR);

//執(zhí)行。

Call.execute();

//取出該部門中的員工的信息。Call中沒有g(shù)etCursor,需要轉(zhuǎn)成OracleCallableStatement

Rs = (OracleCallableStatement)call.getCursor(2);

While(rs.next()) {

String name = rs.getString(“ename”);

double sal = rs.getDouble(“sal”);

System.out.println(name + “ ” + sal);

}

} catch(Exception e) {

e.printStackTrace();

} finally {

JDBCUtils.release(conn,call,rs);

}

}

上面的程序可以在MySQL中跑嗎?不可以,因為實現(xiàn)的是Oracle的接口。

總結(jié)

以上是生活随笔為你收集整理的oracle as 不可以省略,Oracle:存储过程,存储函数的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。