关于存储过程、包
存储过程是存储在数据库中的用户自定义的程序通俗叫法。
根据Oracle
的操作手册,与SQL/PSM
相似的功能可以分为以下三个部分,
·PL/SQL procedure / stored procedure (CREATE PROCEDURE~)
·PL/SQL function / stored function (CREATE FUNCTION~)
·PL/SQL package / stored package (CREATE PACKAGE~ & CREATE PACKAGE BODY~)
都以stored subprogram
称呼,另外,stored procedure
和stored function
都定义为standalone subprogram
。
关于Stored subprogram(stored procedure)
Oracle
所谓的stored procedure
就是PL/SQL
中以Oracle
独自“手续型”语言记述的具有名字的功能模块。
随便举个例子:
1.
接收入口参数
2.
访问数据库中的数据
3.
利用内部变量计算,处理
4.
对数据库的访问,更新,增加,删除等
5.
返回返回值
编写执行这样的一连串的处理的程序,然后
1.
把编写的源代码,或者是不太有把握的源代码存到数据库中
2.
把程序设为手动编译,或者是可以Oracle
自动再编译的状态
3.
把编译完的程序在数据库服务器上执行
4.
把执行结果返回给客户端
这种能被Oracle DBMS
存储并且执行的模块。
在Oracle
数据库中,嵌入了PL/SQL
的源代码编译器以及PL/SQL
的执行引擎。最新的版本中带条件的编译器(Oracle 10g R2
)和非中间代码native
编译环境(Oracle 9i
)也都具备了。
Stored procedure和stored function的区别
Function
包括procedure
的功能,
可以说有了返回值的procedure
就是function
。与拥有返回值的procedure
不同的地方就是SELECT expr FROM tablename
中的expr
的写法,如果把procedure
写入select
的话,如下,
SQL> select func_dummy() from dual; --
可以调用
function
FUNC_DUMMY()
------------
1
SQL> select proc_dummy() from dual; --
不能识别
procedure
select proc_dummy() from dual
*
1行出现错误。:
ORA-00904: "PROC_DUMMY": 无效的标记。
Procedure
自身没有返回值,但是能够给调用返回一个返回值,不是以返回值的形式,而是以设定成OUT
参数的形式,通过这个OUT
属性的参数或者IN OUT
属性的参数来返回结果值。
Standalone subprogram和stored package的差别
Stored package
是stored procedure
和stored function
的集合,但是package
里面不仅仅有这两种东西,它是各个模块的共同住宅,高级公寓一样的东西。
Package
与procedure
集合相比较明显的优点是:
·有可以共同利用的空间
·可以定义在package
内共有而外部不可访问的变量,类型,procedure, function,
用户子定义的例外等。
·可以声明同一session
的package
和procedure
公开的public
变量,procedure
用户定义例外等。
·可以对package内的subprogram使用overload
·为了package不被从共有池里挤出来,可以在DBMS_SHARED_POOL package设定keep。
·有了package,简化了模块间的依存关系(对系统和对人的管理都简化了)
·与standalone subprogram相比,不容易发生共有池的溢出和再装载。同时还可以防止共有内存碎片化。
并不是只有这个可以设定package
为单位,程序中也可以声明,package
并不是具有了所有的优点。在很多情况下,package
的可维护性良好是使用PL/SQL
项目的基础。
PL/SQL的异常处理
根据Exception来进行异常处理
PL/SQL的begin和end之间发生的异常通过在这个块中定义的exception来处理。同一块中没有异常处理定义的情况下,则引用上层的意外处理。
例如虽然捕捉了异常,但是在异常处理部分什么也没写的情况下什么也不会发生。但是如果不进行异常再调用,块内的异常处理被判断为执行,则不通知上层的块。
BEGIN
<程序段>
EXCEPTION
WHEN <异常名> THEN
<异常处理>
END;
带有异常处理的PL/SQL块定义
在异常处理中,如果有多个when,可以分开处理。
如果想同时处理多个异常,则用 when 异常名 or 异常名 or 。。。
例:发生的所有异常都是什么都不处理然后结束(不显示消息)。
DECLARE
vNum NUMBER(2);
BEGIN
vNum := 1 / 0;
DBMS_OUTPUT.PUT_LINE('数値=' || vNum);
EXCEPTION
WHEN OTHERS THEN
NULL; -- NULL; --什么都不处理
END;
/
Others异常是特殊的异常名,包括所有的异常。但是others不能和其他的异常一起进行处理。
多个例外处理的写法以及调用上层异常处理的方法
在发生除零例外的时候显示错误信息。在发生除零异常的时候,发生异常的本身不能向上层抛出。除零异常以外的所有异常发生的时候在异常处理的部分使用RAISE来向上层抛出这个异常。
DECLARE
vNum NUMBER(2);
BEGIN
-- ZERO DIVIDE EXCEPTION
vNum := 1 / 0;
DBMS_OUTPUT.PUT_LINE('数値=' || vNum);
EXCEPTION
WHEN ZERO_DIVIDE THEN
DBMS_OUTPUT.PUT_LINE('不能进行计算');
WHEN OTHERS THEN
-- < 异常処理 >
RAISE;
END;
/
Others异常是包括所有异常的异常名,必须要写在异常处理的最后,否则会出现变异错误(因为会把后面的异常处理器给覆盖)。
嵌套块的异常处理
DECLARE
vNum NUMBER(2);
BEGIN
BEGIN
-- ZERO DIVIDE EXCEPTION
vNum := 1 / 0;
EXCEPTION
WHEN ZERO_DIVIDE THEN
NULL;
END;
EXCEPTION
WHEN OTHERS THEN
< 异常処理 >
RAISE;
END;
/